【问题标题】:Call Stack limitation in C# [duplicate]C# 中的调用堆栈限制 [重复]
【发布时间】:2015-07-02 03:53:14
【问题描述】:

我想知道在我们得到堆栈溢出异常之前,我们可以在 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,但这个数字不是恒定的,所以这是如何工作的?

【问题讨论】:

  • 技术上,编译器不会抛出这个异常,运行时会。
  • 嗯...这是怎么回事?@BradleyDotNET
  • 堆栈中的空间量是恒定的,而不是函数调用的数量是恒定的。

标签: c# stack-overflow callstack limits


【解决方案1】:

每个线程都有一个堆栈大小。程序主线程的预定义堆栈大小在 exe 文件中是固定的。您进行的每个递归调用,都会消耗一些此堆栈。当你完成它时,CLR 会抛出一个StackOverflowException。对于控制台/图形程序,默认堆栈大小应为 1mb 内存。您不能从程序内部使此内存“更大”(您可以使用 editbin.exe 从程序“外部”更改它)。这种记忆不是动态的。它是固定的(从技术上讲,为这块内存保留的地址空间是固定的,内存实际上是由 Windows 操作系统按需分配的,一次可能是 4kb,但始终取决于保留的地址空间)。您可以创建具有所需堆栈大小的辅助线程。

注意这种方式对栈的处理是x86/x64架构的限制,http://en.wikipedia.org/wiki/Stack-based_memory_allocation

某些处理器系列,例如 x86,具有用于操作当前执行线程的堆栈的特殊指令。其他处理器系列,包括 PowerPC 和 MIPS,没有明确的堆栈支持,而是依赖约定并将堆栈管理委托给操作系统的应用程序二进制接口 (ABI)。

【讨论】:

  • 参数的大小是否会影响方法中的堆栈或变量的大小?
  • 在 .NET 的默认实现中,堆栈主要由三样东西填充:未被匿名函数“关闭”的局部变量/yield/async(这些其他变量被移动到单独的类),堆栈跟踪的一些数据,finally/catch 的一些数据。注意,一个引用类型在栈上只占用引用的大小,所以(局部变量)int[] a = new int[100] 占用栈上引用的空间,加上堆中某处的new int[100] 的大小。
  • 感谢您的回答 ;)...我希望 .net 更智能...例如在调用之间找到无限循环然后抛出异常 @xanatos
  • @M.kazemAkhgary,了解Halting problem
猜你喜欢
  • 2011-04-13
  • 2011-09-25
  • 2012-11-18
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 2021-02-17
相关资源
最近更新 更多