如何调试无痕崩溃

dar*_*rak 4 c c++ windows debugging c++builder

在开发应用程序期间,我们特别遇到了一个非常讨厌的bug.症状很简单,该过程消失了.日志突然结束,没有崩溃转储或任何可以找到的东西,没有僵尸进程存在.沃森博士没有注意到任何遗留下来的东西.

该错误不易复制,重现此错误平均需要3-4小时,重复执行相同的操作.所以在某个地方存在某种竞争条件.我们有处理SEH和普通异常的特殊函数,所以这些都不会被忽视.

调试必须在特殊的计算机上完成,因为它运行在非常专业的硬件上.因此只能进行远程调试.当连接远程调试时,C++构建器没有注意到应用程序丢失,当我们尝试对不存在的进程进行任何调试时崩溃并烧毁.

我们在这个软件上使用了各种各样的技术:

  • OpenGL的
  • Directshow +一些COTS过滤器
  • COM/DCOM
  • 串行COM端口与专用硬件通信
  • C++ Builder(使用与VC++不同的堆栈帧)

所以,正如你所理解的那样,我在这里没有多少工作要做.我现在正在做的是我试图通过登录代码中的不同位置来缩小它,以查找代码中是否存在错误发生的特定点.我也试图删除我正在执行的操作的许多方面,以使案例尽可能简单.但这是一个非常复杂的操作,这个过程需要花费很多时间,而且时间(像往常一样)是一种稀缺资源.

我想知道是否有人对我有好的建议,要么是因为(一般是什么导致过程只是在没有任何通知的情况下停止),或者是调试这种难以捉摸的失败的技术?

Zoo*_*oba 7

当Windows下的本机代码遇到堆栈溢出(通常是由于无限递归)时,该过程有时会像您描述的那样完全消失.标准错误对话框和异常处理需要一些堆栈空间,如果没有,则无法运行.(Windows的更高版本处理得更好,应该总是引发异常 - 在此定义下,Windows XP不会"稍后".)

调试它的最简单的暴力方法是在每个函数的入口(可能是出口)处写入日志消息.这些消息必须直接转到文件,如果你有缓冲输出(例如cout或类似),你应该每次立即刷新它.当您设法导致崩溃时,您将接近堆栈跟踪,至少可以本地化问题.


无限递归不是堆栈溢出的唯一原因(尽管它是更常见的).如果在堆栈上分配非常大的变量(通常是具有数千/百万元素的数组),则可能发生相同的问题.特别是,alloca()"函数"可以掩盖这种类型的堆栈溢出的原因.

如果您在调试器下运行并中断/登录防护页面异常,则会在堆栈扩展时通知您 - 请处理异常,因为它用于提交更多内存,实际上可能与该问题无关.


消失过程的最终非堆栈溢出原因是对exit()or 的迷路调用ExitProcess().全文搜索应该能够主要排除这一点 - ExitProcess调试器中的函数断点将完全这样做.

  • 提及编写自己的跟踪日志的+1.在尝试调试隐藏的东西时,每一点日志信息都像Gold一样! (2认同)
  • @daramarak它取决于系统.我刚写了一个简短的测试应用程序(在程序集中,`start:push 0 jmp start`),它在Win7 x64上引发了`STATUS_STACK_OVERFLOW`但在WinXP x86上消失了.您可以尝试的另一件事是减少堆栈限制(应该在链接器选项中)并查看错误是否更快发生. (2认同)