3

我什至不知道是什么导致了我的应用程序。它是什么?我创建了一个类的新实例(该类在另一个文件中),但在第一次调用一个方法时,它会引发 StackOverFlow 异常。

我认为逻辑上唯一会引发 stackoverflow 异常的事情是,如果有人对 Jon Skeet 投了反对票。

但现在说真的,它是什么?我通过在与第一个类相同的文件中创建另一个类并使用它为我调用方法来解决它。

4

9 回答 9

6

作为一般规则,堆栈溢出异常是由递归算法引起的,其中递归深度已超过(通常)固定堆栈限制。这通常是算法中的错误导致的,但也可能是由于您应用算法的数据结构太“深”造成的。

这是一个错误递归的简单示例(在没有特定的 PL 中)。

function int length(list l) {
    if (empty(l)) {
        return 0;
    } else {
        return 1 + length(l);  // should be 'return 1 + length(tail(l));
    }
}

任何非空列表的调用长度都会在典型的编程语言中产生堆栈溢出。但是即使你改正了这个bug,对长列表调用方法也很可能导致堆栈溢出。

(例外情况是当您使用一种语言......或更严格地说是编译器......支持尾递归优化。)

于 2009-09-20T03:16:14.943 回答
4

堆栈溢出异常是当您超出分配的堆栈大小时,这通常发生在递归调用方法并且永不离开时,也可能是由各种模糊的方法链接引起的。问题是您可能在对象中有以下内容。

void MyMethod()
{
    MyMethod();
}

调用将耗尽并且永远不会释放使用的堆栈空间,因为调用永远不会结束执行并且入口点必须保留。

PS SO 以所讨论的特定异常命名(这是基本的,不限于 .NET),它只是开发人员站点的一个聪明的名称。

于 2009-09-20T03:17:48.233 回答
2

StackOverFlows 异常正是它们听起来的样子,堆栈溢出。通常这是因为您的方法中有循环依赖。例如,方法 A 调用 B,B 调用 A。或者它可能是没有基本情况的递归方法。

于 2009-09-20T03:16:29.320 回答
2

如果没有看到代码,就不可能知道为什么会发生这种情况,但是StackOverflowException当线程溢出其调用堆栈时会抛出 a 。这最常发生在方法以递归方式调用自身而没有任何条件中断从而创建无限递归时。由于每次递归都会创建一个新的堆栈帧,因此理论上无限递归会创建无限数量的堆栈帧,我相信您现在可以理解为什么“堆栈溢出”这个术语是恰当的了。

于 2009-09-20T03:16:38.120 回答
2

堆栈是计算机存储当前正在调用的函数列表以及使用的变量和参数的地方。因此,如果函数 Main 调用函数 A,然后函数 A 调用函数 B,并且它们使用变量 c、d 和 e,则堆栈将包含所有这些信息。但是,堆栈只有这么大。因此,如果函数 B 然后调用函数 C,该函数调用函数 D... 等等,最终会产生数百个嵌套函数,最终,堆栈将“溢出”——没有足够的空间来存储另一个函数调用。

正如其他人所指出的,这通常发生在递归函数中(函数 B 调用函数 B,然后函数 B 调用函数 B ...) - 最终,堆栈将溢出。您将需要找到调用该递归函数的位置,以及为什么它没有在应该的递归循环中跳出。

当然,问题可能不在于它是一个有缺陷的递归算法——它可能只是函数调用的数量超过了堆栈的大小。所以如果你的算法有可能调用一个递归函数几百次,它可能就是这样。

于 2009-09-20T03:25:25.860 回答
1

这通常是由对递归调用永远不会终止的函数的递归调用引起的。您可以通过多种方式获得此信息。一种方法可能是没有基本情况的递归算法,另一种常见的方法是创建对象 A 和 B,它们在它们的构造函数中相互创建,等等。

我建议你逐步调试并找出:)

于 2009-09-20T03:18:27.383 回答
0

我最近将一个旧的 VB6 应用程序移植到 VB.NET,它使用了一个可怕的递归函数来对同样大量的数据进行排序。该算法很好,但执行始终导致堆栈溢出错误。经过一番折腾,我意识到 VB 在代码背后做了很多魔法:简单的类型转换是有代价的。所以递归函数过于依赖后期绑定而不是使用类型变量,这导致了大量的转换、解析等开销(一行代码可以调用 2 到 10 个函数......)其中,显然,使堆栈溢出。

TL;DR:使用 DirectCast() 和静态绑定(类型化变量)来防止 VB 在运行时以递归函数淹没堆栈。

于 2014-06-26T19:20:43.787 回答
0

我遇到了这个问题,我注意到我输入了错误的 lstEncounter。正如我在我的 C++ 课程中学到的,问题在于递归算法基本上使用相同的参数调用自身。我收到错误的示例:

Property Encounter(ByVal N As Integer)
    Get
        If N < lstEncounters.Count Then
            Return Encounter(N)
        Else
            Return Nothing
        End If
    End Get
    Set(value)
        lstEncounters(N) = value
    End Set
End Property
于 2014-12-25T05:44:45.493 回答
-1

我遇到了 Stackoverflow 错误。我正在使用一个将 1 添加到计数器的例程,然后重新调用相同的例程。大约每 2500 到 3000 个循环,我就会收到 stackoverflow 错误。我添加了一个调用例程的 DO...循环,我使用 VB Express:

前:

Public Sub mainloop()

Dim cntr as integer

If cntr >= 5000  ( I just picked a number at random)

    me.close  ( I close the program)

...               (This is where I would manipulate the cntr for diff 
results)

cntr = cntr + 1  ( increment the cntr)

mainloop()        (re call my loop) 

End IF

End Sub

(正如我之前所说,大约 2500-3000 之后我会收到 Stackoverflow 错误)

之后:(先执行这个)

Dim LoopCntr as integer

Do While LoopCntr <= 40000  (this my number.. Use your own number)

If LoopCntr > 40000 Then

        Exit Do
End If

mainloop()       (The mainloop() has not been changed just the method of calling it)
LoopCntr = LoopCntr + 1

Loop

me.close        (When LoopCntr reaches max it closes the program)

(添加 Do..Loop 后,我的程序在没有“Stackoverflow”的情况下运行了 40000 次)

于 2017-07-01T16:46:34.413 回答