2015-04-23 67 views
4

我不知道有多少电话,我们可以在C#之前,我们得到堆栈溢出异常在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。对于控制台/图形程序,默认堆栈大小应为1mb内存。您不能从程序内部将此内存“更大”(可以使用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 –