【问题标题】:Running down a 'stack overflow' bug运行“堆栈溢出”错误
【发布时间】:2010-12-22 19:52:06
【问题描述】:

我有一个用 Delphi W32 编写的应用程序,它处于测试阶段。

在测试 PC 上,使用几个小时后,它会随意弹出“堆栈溢出”消息。

如何捕获错误并找到原因?

我可以增加堆栈大小吗?

【问题讨论】:

  • 提高堆栈大小几乎肯定只会减少不可避免的问题,也许您应该减少它以便更早地发现问题?

标签: delphi stack-overflow


【解决方案1】:

您应该减少链接器选项中的堆栈大小。然后在调试器下运行它,希望问题会出现,而无需等待两个小时。

【讨论】:

  • 好主意!!非常聪明的方法可以更快地发现错误。尽管您必须在某处记下旧堆栈值... ;-) +1
【解决方案2】:

获取madExcept,它会准确告诉您故障发生时发生的情况。你会看到完整的堆栈,尤其是在它逃跑的地方。

【讨论】:

  • +1 当然,您也可以使用任何其他异常跟踪框架(EurekaLog 或 JCL 仅举两个例子)。
  • +1。 MadExcept 和 JclDebug 是你离不开的东西。
  • 哦,你考虑过无限递归吗?您的递归算法是否在最大深度检查并引发异常?
【解决方案3】:

我几乎要说:在调试器中运行它;^)

我以前做的是在每个方法中添加一个进入和离开日志功能。通过适当的缩进,我可以在日志中追踪调用路径。

当发生堆栈溢出时,它会在日志中真正可见,因为缩进级别应该是通过屋顶

 void someMethod()
 {
      logMethodEnter("someMethod");

      ... do stuff...
      log("something")
      ... do stuff...

      logMethodLeave("someMethod");

 }

记录器会跟踪当前的日志深度并记录如下内容:

 >someMethod
   something
 <someMethod

【讨论】:

    【解决方案4】:

    您是否在测试机器上安装了 IDE?如果是这样,请尝试从 IDE 中重现该问题。当发生堆栈溢出时,查看调用堆栈(View->Debug Windows->Call Stack)。它可能会多次调用相同的函数,如下所示:

    FunctionA
    FunctionB
    FunctionA
    FunctionB
    FunctionA
    FunctionB
    ...
    

    如果你看到了,那么你就知道这些函数在没有结束的情况下互相调用。

    如果您没有在测试机器上安装 IDE,那么您仍然可以通过远程调试来执行此操作。如果您提供有关您的方案的更多信息,我们可能会提供更多帮助。

    具体来说,了解一下可能会有所帮助:

    • 你能重现它吗?
    • 是否安装了IDE测试 机器?
    • 什么版本的 Delphi?

    【讨论】:

      【解决方案5】:

      您可以使用项目链接器选项或 $M 编译器指令增加堆栈大小,但我认为除非堆栈非常小,否则它不会解决问题。

      如果您在调试器中运行应用程序,它最终会在异常处中断。

      【讨论】:

        【解决方案6】:

        如果您使用线程(不是主 ex:sock 连接)和主线程,那么它们共享同一个堆栈。以这种方式解决:只需为每个连接创建一个具有自己堆栈的线程。

        问题 > 你做的每一个调用都会为帧调用堆栈(共享一个这么大的问题) 例如,您调用 proc aa(a,b:integer) 例如始终调用相同或不同的函数;

        您有一个套接字线程正在运行,并且 onconnect 您调用 proc a;并保持做某事需要 5 秒。

        如果有人在 on connect close 连接(释放堆栈)之前连接。 您有 2 个连接的客户端(2 个不同的堆栈帧,每个不同的数据)

        堆栈

        推 a,b (整数);值 5,10 - 来自 1 个连接

        推 a,b (整数);值 7,3 - 来自 2 conn

        如果 onconnect 调用函数 a(5,10) 并保持做某事大约 5 秒。 并且有人再次连接到服务器套接字,它再次调用连接。

        堆栈旧第一个调用帧但还没有退出 proc。所以没有从 (5,10) 弹出 a,b

        如果您再次调用 proc 会比这更复杂,那么它将覆盖 2 帧上的数据(2 个连接的本地 proc 变量),因此当 2 个连接从堆栈获取数据时,肯定已经被其他信息覆盖。所以它会做不正确的行为。

        当第一个连接断开时会弹出 a,b 但 7,3(来自第二个连接)而不是它保存的 5,10。因此它不会立即堆栈溢出,而是稍后随着程序运行和堆栈释放错误,您最终会得到一个$FFFFFFFF $SP 堆栈。所以当你调用一个函数时它会尝试$FFFFFFAA,所以它比你的堆栈大:$M 65536,而不是$FFFFFFAA的4 GB。

        【讨论】:

          猜你喜欢
          • 2013-09-11
          • 2021-05-28
          • 2014-01-26
          • 2019-02-16
          • 2011-09-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多