请定义堆栈溢出异常 - c#

Luk*_*ger 0 c# stack-overflow methods compiler-errors function

我不确定堆栈溢出异常是什么.当我以另一种形式调用方法时,我收到此错误.

Ric*_*key 7

有时程序行为不端.程序员通过实现一些逻辑然后测试它是否正常工作来编写程序.但如果程序员在逻辑上犯了错误,就会发生坏事.

程序可能出错的最常见方式之一可能是无限循环.拿这个尝试添加前n个整数的示例程序:

static int Sum(int n)
{
    int sum = 0;
    int i = 1;
    while (i <= n)
        sum += i;
    return sum;
}
Run Code Online (Sandbox Code Playgroud)

会发生什么?错误在哪里?我们忘了增加i,所以永远不会超过n.当你运行它时,它会运行并挂起.它永远不会停止.

但是如果你在程序中有一个无限循环并且你在该循环中使用资源,那么你可能会耗尽资源.让我们采用另一个使用递归来查找总和的程序:

static int RecursiveSum(int n)
{
    return n + RecursiveSum(n - 1);
}
Run Code Online (Sandbox Code Playgroud)

这种方法也有问题.它也有一个"无限循环"因为我们忘了包含终止条件.运行时会发生什么?

由于StackOverflowException,进程终止.

在C#中,每次调用方法时,都会占用一些称为堆栈的资源.堆栈允许程序跟踪谁调用谁,以便在方法返回时,它返回到正确的位置.方法参数和局部变量也会占用堆栈空间.当方法结束并返回时,它们释放了它们使用的堆栈空间.

问题是堆栈使用内存,因此它不像时间那样是无限的资源!

因此,程序可以通过两种主要方式生成StackOverflowException:

  1. 一个无限循环的方法调用方法调用永不返回的方法
  2. 一系列过多的递归调用级别最终将会结束,但堆栈会先耗尽

上面的第二种方法证明了第一个问题.但即使我们修复了这种方法来添加终止条件,虽然它适用于较小的数字,但在产生足够大的n值之和之前它最终会失败.

大多数花园品种StackOverflowException都是第一种类型,但如果你不在方法中小心使用递归,你也会遇到第二个问题.

调试时StackOverflowException,调用堆栈通常如下所示:

...
Program.RecursiveSum(int n = -7770) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7769) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7768) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7767) Line 26 + 0xf bytes C#
Program.RecursiveSum(int n = -7766) Line 26 + 0xf bytes C#
The maximum number of stack frames supported by Visual Studio has been exceeded.    
Run Code Online (Sandbox Code Playgroud)

或者有时A调用B哪个调用C然后再调用A等等.你只需找到循环,设置一个断点,诊断发生了什么.


SLa*_*aks 6

一个堆栈溢出,当你有太多的方法调用每个-等发生.

每当您的代码调用一个函数时,运行时将一个条目推送到一个调用堆栈,标记您在调用该函数时所处的位置.当函数完成时,运行时将ntry从堆栈中弹出并返回到那里.

当此堆栈满时发生堆栈溢出.