所以我正在尝试调试这个奇怪的问题,其中一个进程结束而不调用一些析构函数......
在VS(2005)调试器中,当我看到这个时,我点击'Break all'并查看大量消失过程的线程的调用堆栈:
smells like SO http://img6.imageshack.us/img6/7628/95434880.jpg
这绝对看起来像是制作中的SO,这可以解释为什么这个过程会在没有先装好行李箱的情况下运行到它的快乐地方。
问题是,VS调试器的调用堆栈只显示您在图像中可以看到的内容。
所以我的问题是:如何找到无限递归调用的起始位置?
我读到somewhere在Linux中你可以附加一个回调给SIGSEGV处理程序,并获得有关正在发生的事情的更多信息。
Windows上有类似内容吗?
答案 0 :(得分:3)
要控制Windows在发生访问冲突时所执行的操作(SIGSEGV
- 等效),请调用SetErrorMode
(传递参数0以在发生错误时强制弹出窗口,允许您使用调试器附加到它。)
但是,根据您已经获得的堆栈跟踪,在发生故障时附加调试器可能不会产生任何其他信息。您的堆栈已损坏,或递归深度已超过VS可显示的最大帧数。在后一种情况下,您可能希望减少流程的默认堆栈大小(使用项目属性中的/F
开关或等效选项)使问题更快地显现,并确保VS 将显示所有帧。或者,您可以在std :: basic_filebuf<> :: flush()中粘贴一个断点,然后遍历它直到破坏阶段(或禁用它直到破坏阶段之前。)
答案 1 :(得分:3)
嗯,你知道这个问题的主题是什么 - 它可能是一个简单的问题,从一开始就跟踪它,看看它在哪里进入杂草。
另一种选择是使用Debugging Tools for Windows包中的一个调试器 - 它们可能比VS调试器(可能)显示更多,即使它们通常更复杂且难以使用(实际上可能)因为那个。)
答案 2 :(得分:1)
乍一看就像无限递归一样,你可以尝试在终止进程之前在该行放置一个断点。它到那儿好吗?如果是这样,你有两个相当容易的方法。
要么你只是前进一步,看看哪些析构函数被调用,什么时候被调用。或者你可以在每个相关的对象析构函数中放置一个printf / OutputDebugString(只有全局变量才需要这个)。如果消息是析构函数所做的第一件事,那么你看到的最后一条消息来自析构函数,它会挂起来。
另一方面,如果它没有达到我最初提到的那个断点,那么可以做类似的事情,但是因为程序仍在“做事”,所以会更烦人。
答案 3 :(得分:0)
我不排除在Windows中有这样的处理程序,但我从未听说过它。
我认为你所展示的追溯可能是虚假的。如果您在已经发生某种损坏后进入该过程,则回溯不一定有效。但是,如果你很幸运,堆栈跟踪的底部仍然有一些关于发生了什么的线索。
尝试将Sleep()
调用放入源中可能涉及递归的选定函数中。这应该会让你有更好的机会在堆栈完全溢出之前进入进程。
答案 4 :(得分:0)
我同意Dan Breslau的观点。你的筹码是假的。可能只是因为你没有正确的符号。 如果程序在没有WER处理的情况下完全消失,则通常是内存不足的情况。你有没有调查那种可能性?