有时我的 c++ 程序在调试模式下崩溃,我得到的是一个消息框,说某些内部内存管理例程中的断言失败(访问未分配的内存等)。但我不知道从哪里调用它,因为我没有得到任何堆栈跟踪。如何获取堆栈跟踪或至少查看它在我的代码中失败的位置(而不是库/内置例程)?
7 回答
如果发生崩溃,无论您有调试版本还是发布版本,都可以获得有关崩溃发生位置的信息。即使您在没有源代码的计算机上,您也可以看到调用堆栈。
为此,您需要使用通过 EXE 构建的 PDB 文件。将 PDB 文件放在与崩溃的 EXE 相同的目录中。注意:即使您有相同的源代码,构建两次并使用第一个 EXE 和第二个 PDB 也不起作用。您需要使用与您的 EXE 一起构建的确切 PDB。
然后将调试器附加到崩溃的进程。示例:windbg 或 VS。
然后只需检查您的调用堆栈,同时打开您的线程窗口。您必须选择崩溃的线程并检查该线程的调用堆栈。每个线程都有不同的调用堆栈。
如果您已经连接了 VS 调试器,它将自动转到导致您崩溃的源代码。
如果崩溃发生在您使用的没有 PDB 的库中。你无能为力。
如果您在带有 VS 的机器上运行调试版本,它应该会提供启动它并让您查看堆栈跟踪。
问题是真正的问题不再在调用堆栈上。如果您两次释放指针,则可能会在与程序无关的其他地方导致此问题(下一次访问堆数据结构时)
我写了这篇博客,介绍了一些让问题出现在调用堆栈中的技巧,这样你就可以弄清楚发生了什么。
最好的提示是使用 gflags 实用程序使指针问题立即引起问题。
如果我没记错的话,那个消息框应该有一个按钮,上面写着“重试”。这应该在断言发生的地方中断程序(在调试器中)。
CrashFinder可以根据 DLL 和报告的异常地址帮助您定位异常的位置。
您可以使用此代码并将其集成到您的应用程序中,以便在出现未捕获的异常时自动生成堆栈跟踪。这通常使用__try{} __except{}
或调用SetUnhandledExceptionFilter来执行,它允许您指定对所有未处理异常的回调。
You can also have a post-mortem debugger installed on the client system. This is a decent, general way to get information when you do not have dump creation built into your application (maybe for an older version for which you must still get information).
Dr. Watson on Windows can be installed by running: drwtsn32 -i
Running drwtsn32
(without any options) will bring up the configuration dialog. This will allow the creation of crash dump files, which you can later analyze with WinDbg or something similar.
You can use Poppy for this. You just sprinkle some macros across your code and it will gather the stack trace, together with the actual parameter values, local variables, loop counters, etc. It is very lightweight so it can be left in the release build to gather this information from crashes on end-user machines