5

所以我试图调试这个奇怪的问题,一个进程在没有调用一些析构函数的情况下结束......

在 VS (2005) 调试器中,当我看到以下内容时,我点击了“Break all”并查看了神秘消失进程的线程的调用堆栈:

闻起来像 SO http://img6.imageshack.us/img6/7628/95434880.jpg

这绝对看起来像一个正在制作的 SO,这可以解释为什么这个过程会在没有先打包手提箱的情况下运行到它快乐的地方。

问题是,VS 调试器的调用堆栈只显示您在图像中看到的内容。

所以我的问题是:我怎样才能找到无限递归调用的开始位置?

我在某处读到,在 Linux 中,您可以将回调附加到 SIGSEGV 处理程序并获取有关正在发生的事情的更多信息。

Windows上有类似的东西吗?

4

5 回答 5

3

要控制 Windows 在访问冲突SIGSEGV-equivalent)的情况下做什么,请调用 SetErrorMode(传递参数 0 以在出现错误时强制弹出窗口,允许您使用调试器附加到它。)

但是,根据您已经获得的堆栈跟踪,在故障时附加调试器可能不会产生任何附加信息。您的堆栈已损坏,或者递归深度已超过 VS 可显示的最大帧数。在后一种情况下,您可能希望减小进程的默认堆栈大小(使用/F项目属性中的开关或等效选项)以使问题更快地显现出来,并确保 VS显示所有帧。或者,您可能希望在 std::basic_filebuf<>::flush() 中放置一个断点并遍历它直到破坏阶段(或禁用它直到破坏阶段之前。)

于 2009-04-02T15:42:23.423 回答
3

好吧,您知道问题出在哪个线程上——这可能是一个简单的问题,从一开始就跟踪它,看看它从哪里进入杂草。

另一种选择是使用Debugging Tools for Windows包中的一个调试器 - 它们可能比 VS 调试器显示更多(也许),即使它们通常更复杂且难以使用(实际上可能是因为那个) .

于 2009-04-02T16:02:58.337 回答
1

乍一看确实像无限递归,您可以尝试在终止进程的行之前放置一个断点。它可以到达那里吗?如果是这样,你有两种相当简单的方法可以走。

要么你向前一步,看看哪些析构函数被调用,什么时候被赶上。或者您可以在每个相关的对象析构函数中放置一个 printf/OutputDebugString(只有全局对象才需要这个)。如果消息是析构函数做的第一件事,那么你看到的最后一条消息来自析构函数,它把事情挂了。

另一方面,如果它没有到达我最初提到的那个断点,那么可以做类似的事情,但这会更烦人,因为程序仍在“做事”。

于 2009-04-02T14:33:45.327 回答
0

我不排除在 Windows 中有这样的处理程序,但我从未听说过。

我认为您显示的回溯可能是虚假的。如果您在某种损坏已经发生后闯入该过程,那么回溯不一定有效。但是,如果幸运的话,堆栈跟踪的底部仍然有一些关于正在发生的事情的线索。

尝试将Sleep()调用放入源中可能涉及递归的选定函数中。这应该让您有更好的机会在堆栈完全溢出之前进入进程。

于 2009-04-02T14:04:24.447 回答
0

我同意丹·布雷斯劳的观点。你的堆栈是假的。不过,可能只是因为您没有正确的符号。如果一个程序在没有启动 WER 处理的情况下就消失了,这通常是内存不足的情况。你去调查过这种可能性吗?

于 2009-04-03T23:27:23.187 回答