2015-04-23 6 views
4

Интересно, сколько звонков мы можем выполнить в стеке в C#, прежде чем мы получим переполнение стека за исключениеCall Stack ограничения в C#

поэтому я решил написать следующий код

static void Method2(int Calls) 
    { 
     if(!Calls.Equals(0)) 
      Method1(--Calls);//if more calls remain call method1 and reduce counter 
    } 
    static void Method1(int Calls) 
    { 
     if (!Calls.Equals(0))//if more calls remain call method2 and reduce counter 
      Method2(--Calls); 

    } 
    static void Main(string[] args) 
    { 
     var Calls= 42994;//number of calls(stack overflow appears for large number) 
     Method1(Calls); 
    } 

мой вопрос, как компилятор решает выбросить исключение переполнения стека это о ограничениях памяти? как только я положил 42995, я получил stackoverflow, но это число не является постоянным, так как это работает?

+6

Технически компилятор не выбрасывает это исключение, выполняется время выполнения. – BradleyDotNET

+0

хорошо ... как это происходит? @BradleyDotNET –

+2

В стеке есть постоянное количество места, а не постоянное количество вызовов функций. – Gabe

ответ

6

Каждая нить имеет размер стека. Предопределенный размер стека для основного потока программы фиксируется в exe-файле. Каждый рекурсивный вызов, который вы делаете, вы потребляете немного этого стека. Когда вы закончите, CLR выбрасывает StackOverflowException. Для консольных/графических программ размер стека по умолчанию должен быть 1 мб памяти. Вы не можете сделать эту память «большой» изнутри программы (вы можете использовать editbin.exe, чтобы изменить ее из «снаружи» программы). Эта память не является динамической. Он исправлен (технически, адресное пространство, зарезервированное для этой памяти, исправлено, память действительно выделяется операционной системой Windows по требованию, возможно 4kb за раз, но всегда до зарезервированного адресного пространства). Вы можете создавать вторичные потоки с требуемым размером стека.

Обратите внимание, что обработка стека таким образом это ограничение x86/x64 архитектуры, http://en.wikipedia.org/wiki/Stack-based_memory_allocation:

Некоторые процессоры семейства, такие как x86, есть специальные инструкции для манипулирования стек в настоящее время выполнение потока. Другие семейства процессоров, включая PowerPC и MIPS, не имеют явной поддержки стека, но вместо этого полагаются на соглашение и управление потоком делегатов на двоичный интерфейс приложения операционной системы (ABI).

+1

действительно ли размер параметров влияет на размер стека или переменных внутри методов? –

+1

Стек заполняется в основном тремя вещами в реализации по умолчанию .NET: локальные переменные, которые не «закрыты» анонимными функциями/yield/async (эти другие переменные перемещаются в отдельный класс), некоторые данные для трассировка стека, некоторые данные для 'finally' /' catch'. Обратите внимание, что ссылочный тип занимает в стеке только размер ссылки, поэтому (локальная переменная) 'int [] a = new int [100]' занимает пространство ссылки в стеке плюс размер 'new int [100] 'где-то в куче. – xanatos

+0

спасибо за ответ;) ... я хотел бы .net был более умным ... например, найти бесконечный цикл между вызовами и затем исключить исключение @xanatos –