C ++程序崩溃时如何获取堆栈跟踪? (使用msvc8 / 2005)
有时我的c ++程序在调试模式下崩溃,我得到的是一个消息框,指出某些内部内存管理例程中的断言失败(访问未分配的内存等)。但是我不知道从哪里调用的,因为我没有得到任何堆栈跟踪。如何获得堆栈跟踪或者至少查看代码失败的地方(而不是库/内置例程)?
解决方案
如果发生崩溃,则无论是调试还是发布版本,都可以获取有关崩溃发生位置的信息。即使我们在没有源代码的计算机上,也可以看到调用堆栈。
为此,我们需要使用与EXE一起生成的PDB文件。将PDB文件与崩溃的EXE放在同一目录中。注意:即使我们具有相同的源代码,也无法两次构建并使用第一个EXE和第二个PDB。我们需要使用与EXE一起构建的确切PDB。
然后将调试器添加到崩溃的进程。例如:windbg或者VS。
然后只需签出调用堆栈,同时还可以打开线程窗口。我们将必须选择崩溃的线程,并在调用堆栈中检查该线程。每个线程都有一个不同的调用堆栈。
如果我们已经连接了VS调试器,它将自动转到导致崩溃的源代码。
如果崩溃发生在我们正在使用的库中,则说明我们没有PDB。我们无能为力。
如果我没记错的话,该消息框中应该有一个显示"重试"的按钮。然后,这将在断言发生时中断程序(在调试器中)。
如果我们在装有VS的计算机上运行调试版本,则应提供调试版本,并让我们查看堆栈跟踪。
问题是真正的问题不再在调用堆栈上。如果释放指针两次,则可能在与程序无关的其他地方导致此问题(下一次任何访问堆数据结构的事件)
我在这个博客上写了一些技巧,以使问题出现在调用堆栈中,以便我们了解发生了什么。
http://www.atalasoft.com/cs/blogs/loufranco/archive/2007/02/06/6-2200_Pointers_2200-on-Debugging-Unmanaged-Code.aspx
最好的技巧是使用gflags实用程序使指针问题引起直接问题。
CrashFinder可以在给定DLL的情况下找到异常的位置,并报告异常的地址。
我们可以采用此代码并将其集成到应用程序中,以在发生未捕获的异常时自动生成堆栈陷阱。通常使用__try {} __except {}
或者调用SetUnhandledExceptionFilter来执行,该调用允许我们为所有未处理的异常指定回调。
我们可以通过为未捕获的异常设置处理程序来触发小型转储。这是一篇介绍小型转储的文章
Google实际上实现了他们自己的名为BreakPad的开源崩溃处理程序,我认为Mozilla也会使用它(也就是说,如果我们想要更严肃,更丰富,更强大的崩溃处理程序)。
本文介绍如何计算堆栈跟踪。
我们还可以在客户端系统上安装事后调试器。当我们没有在应用程序中内置转储创建功能时,这是一种获取信息的不错的常规方法(对于较旧的版本,我们仍必须为其获取信息)。
可以通过运行以下命令在Windows上安装Watson博士:drwtsn32 -i
运行drwtsn32
(不带任何选项)将弹出配置对话框。这将允许创建故障转储文件,我们以后可以使用WinDbg或者类似工具对其进行分析。