1

我有最后期限。我在谷歌搜索,我在阅读代码,我需要帮助......

我的应用程序正在抛出 EStackOverFlow。需要通宵测试才能发现错误,所以我需要一些好的想法,否则需要很长时间才能找到。

我昨晚用 MAD except 尝试过,但没有抓住它,大概是因为没有堆栈可以这样做。我是从 IDE 运行的,所以我中断了执行并查看了调用堆栈,但除了细节之外,它充满了 MAD(我已经联系了作者,但我们之间存在很大的时间差异)。

没有(故意)递归递归例程。没有 OnChange 处理程序(这可能会意外更改它们监视的组件,从而递归调用它们自己)。没有大型数据结构(可能作为参数在堆栈上传递)。

我的第一个想法是关闭 MAD except,但我不能再等 12 或 16 个小时才能崩溃。

在无人看管的情况下,当计时器每 30 秒或每小时到期时,程序正在执行一些数据库访问,所以我将它们设置为 1 秒,希望能加速崩溃。嗯,我可以减少堆栈大小以加速崩溃吗?如果是这样,怎么做?

我还可以做些什么?我已经将我的应用程序主文件包装在 Try ... 中,其中创建了表单并运行了应用程序。

是否有一些点,例如消息处理循环,我可以在其中检查堆栈大小并查看它是否增长“太大”?(如果有,能否提供详细信息?)

还有什么建议吗?提前致谢

(ps代码太大,无法发布)

4

2 回答 2

1

最常见的stackoverflow问题是函数调用本身,尽量避免它,或者至少限制它。

您说您使用计时器,您是在计时器事件中调用 Application.ProcessMessages 吗?如果队列中有很多消息,如果它是另一个 WM_TIMER,这可能会导致堆栈溢出。

于 2012-09-20T09:44:48.693 回答
1

作为。我上面提到的 Profiler 方法可能会给你带来纯粹的运气(如果有一些杂散的分支会导致你发生罕见但即时快速的泄漏。比如说,在 100 个案例变体中,只有一个会导致无限递归)。但是,如果有稳定的累积泄漏,需要整晚才能累积,那么探查器的结果将无法与正常工作区分开来。

我想了一下。当前的假设是堆栈跟踪器失败,因为没有剩余堆栈。让我们抓住它。然后我们将在堆栈结束之前抛出异常,是吗?所以我会尝试这个序列:

1)我将堆栈跟踪器设置为记录完整的堆栈跟踪,包括行号。它可以在 Delphi IDE 使用的 JCL 跟踪器中完成,我认为 madExcept 也可以。

2)我想知道当前的堆栈大小。例如使用 Visual Studio 确定堆栈空间

3)我会定期检查使用的堆栈空间。例如,什么是安全的最大堆栈大小或如何衡量堆栈的使用?

注意:因为我们几乎不知道是哪个线程导致了这个 - 如果我有几个线程,我会尝试使用所有这些。我只是不知道如果某些辅助线程因 SO 而失败,应用程序将如何反应,它是否会被拦截和记录,或者整个应用程序会因为一个线程而被炸毁

4) ~ 每 5 分钟记录一次当前的堆栈使用情况 - 只是为了查看模式,如果它正在稳步缓慢地运行,或者它是一些罕见但严重的代码路径。 如果有多个线程 - 然后每个线程有多个日志文件 它还允许估计“正常”堆栈使用情况。

5)如果堆栈使用率提高到 80% 以上(我认为你上面的“正常”使用 todl 不会超过它,不是吗?)我会提出手动异常,一些特殊类直到线程/应用程序顶部才会被捕获级别,在顶层甚至可能做一些复杂的事情,比如将应用程序暂停到调试器并唤醒你,这样你就可以远程连接并检查生病但尚未死亡的应用程序的内部状态。

于 2012-09-20T06:02:08.847 回答