【问题标题】:c#/vb Stack Overflow Exception on relatively small call stackc#/vb Stack Overflow Exception on相对较小的调用堆栈
【发布时间】:2021-05-26 21:01:32
【问题描述】:

我的 VB.NET DLL 中出现堆栈溢出异常。

调用堆栈有 115 个调用深度,它不是一个有问题的递归程序,但调用堆栈的深度确实需要。

当我想象递归程序比这更深入时,我想知道为什么它会爆炸。有谁知道是什么导致堆栈空间被用完?例如长字符串作为其中一个调用中的参数是否有贡献?或者其他什么会导致它?

我尝试了以下方法

  • 注释掉/恢复最近的更改,但仍然失败
  • 重启
  • 多次运行,它永远不会在同一个地方失败,但总是在随机的地方

代码目前是单线程的,编译为 64 位进程。

我大约一年没有升级 VS,所以不确定是什么变化导致了这个

我知道如何通过在不同线程上启动部分进程然后等待它们来解决此问题,但该解决方案让我担心,因为它更像是一种解决方法/黑客,而不是首先找到导致它的原因。

因此,希望了解可能导致错误的可能因素,并思考什么可能导致堆栈空间如此迅速地填满。

我确信如果在 C# 中迁移程序会继续出错,所以我也用 C# 标记,因为在该语言中同样可能发生错误。

【问题讨论】:

  • 字符串是引用类型,因此它们的长度不会影响堆栈的使用(堆栈上传递的参数将是对字符串的引用),但值类型作为参数传递或用作局部变量可能会用完堆栈空间。你在分配大的Structures 吗?
  • 您是否引入了自引用属性?
  • 有一些大类,但它们还是会通过引用传递。那里的一些函数非常大,有很多变量,但我看不出编译器如何为它们使用堆栈。我认为我们没有任何自引用属性,并且应用程序中没有使用任何结构类型。

标签: c# vb.net stack-overflow


【解决方案1】:

深度会受到方法中发生的事情的影响。我创建了这个示例,它根据编译器变量 foo 获得不同的计数。当 foo 为 true 时,我得到 2799 计数,false 计数为 5364。我必须调整 #if 的位置才能看到计数。

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        test()
    End Sub

    Dim count As Integer = 0

#Const foo = True
    Private Sub test()
        Try
            count = count
            count += 1

            Dim xe As XElement = <breakfast_menu></breakfast_menu>
            xe.Add(<food>
                       <name>Belgian Waffles</name>
                       <price>$5.95</price>
                       <calories>650</calories>
                   </food>)
            xe.Add(<food>
                       <name>Strawberry Belgian Waffles</name>
                       <price>$7.95</price>
                       <calories>900</calories>
                   </food>)
#If foo Then
            xe.Add(<food>
                       <name>Berry-Berry Belgian Waffles</name>
                       <price>$8.95</price>
                       <calories>900</calories>
                   </food>)
            xe.Add(<food>
                       <name>French Toast</name>
                       <price>$4.50</price>
                       <calories>600</calories>
                   </food>)
            xe.Add(<food>
                       <name>Homestyle Breakfast</name>
                       <price>$6.95</price>
                       <calories>950</calories>
                   </food>)

            Dim ie As IEnumerable(Of XElement)
            ie = From el In xe.<food>
                 Where Integer.Parse(el.<calories>.Value) < 900
                 Select el
#End If
            test()

        Catch ex As Exception
            Stop
        End Try
    End Sub

【讨论】:

  • 谢谢,这当然是一个线索。并暗示即使是 sub 中的数据/处理(不是来自参数)也会导致堆栈填满,我觉得这有点令人费解!
  • @user2728841 计算(通常)不会起作用,但局部变量显然会起作用(除非它们可以被省略)。
猜你喜欢
  • 2011-03-23
  • 2017-04-01
  • 2022-12-28
  • 1970-01-01
  • 2012-06-03
  • 2014-06-02
  • 1970-01-01
  • 2017-06-26
  • 2017-04-01
相关资源
最近更新 更多