当C++;程序崩溃?(使用msvc8/2005) 有时我的C++程序在调试模式下崩溃,而我得到的消息框是断言在一些内部内存管理例程中失败(访问未分配的内存等)。但我不知道从哪里调用的,因为我没有得到任何堆栈跟踪。如何在我的代码中获取堆栈跟踪或至少查看它在哪里失败(而不是库/内置例程)?

当C++;程序崩溃?(使用msvc8/2005) 有时我的C++程序在调试模式下崩溃,而我得到的消息框是断言在一些内部内存管理例程中失败(访问未分配的内存等)。但我不知道从哪里调用的,因为我没有得到任何堆栈跟踪。如何在我的代码中获取堆栈跟踪或至少查看它在哪里失败(而不是库/内置例程)?,c++,debugging,visual-studio-2005,stack-trace,C++,Debugging,Visual Studio 2005,Stack Trace,如果发生崩溃,无论是调试版本还是发布版本,都可以获取崩溃发生在哪里的信息。即使在没有源代码的计算机上,也可以看到调用堆栈 要做到这一点,您需要使用用EXE生成的PDB文件。将PDB文件放在与崩溃的EXE相同的目录中。注意:即使您有相同的源代码,构建两次并使用第一个EXE和第二个PDB也无法工作。您需要使用与EXE一起构建的确切PDB 然后将调试器附加到崩溃的进程。示例:windbg或VS 然后简单地签出调用堆栈,同时打开线程窗口。您必须选择崩溃的线程,并检查该线程的调用堆栈。每个线程都有不同的调

如果发生崩溃,无论是调试版本还是发布版本,都可以获取崩溃发生在哪里的信息。即使在没有源代码的计算机上,也可以看到调用堆栈

要做到这一点,您需要使用用EXE生成的PDB文件。将PDB文件放在与崩溃的EXE相同的目录中。注意:即使您有相同的源代码,构建两次并使用第一个EXE和第二个PDB也无法工作。您需要使用与EXE一起构建的确切PDB

然后将调试器附加到崩溃的进程。示例:windbg或VS

然后简单地签出调用堆栈,同时打开线程窗口。您必须选择崩溃的线程,并检查该线程的调用堆栈。每个线程都有不同的调用堆栈

如果已经连接了VS调试器,它将自动转到导致崩溃的源代码


如果崩溃发生在您正在使用的库中,而您没有PDB。您无能为力。

如果我没记错的话,消息框应该有一个按钮,上面写着“重试”。然后,这将在断言发生时中断程序(在调试器中)。

如果您在带有VS的计算机上运行调试版本,它将提供调出该版本并让您查看堆栈跟踪

问题是真正的问题不再出现在调用堆栈上。如果释放一个指针两次,可能会导致与程序无关的其他地方出现此问题(下次任何东西访问堆数据结构时)

我写这篇博客的一些技巧是如何让问题显示在调用堆栈中,这样你就可以知道发生了什么

最好的技巧是使用gflags实用程序使指针问题立即引起问题

可以根据DLL和报告的异常地址帮助您定位异常的位置。

您可以将此代码集成到应用程序中,以便在出现未捕获异常时自动生成堆栈悲剧。这通常是通过使用
\uuuuu try{}\uu{}
执行的,除了{}之外,还可以通过调用来指定对所有未处理异常的回调。

您可以通过设置未捕获异常的处理程序来触发小型转储。这里有一个解释小型转储的例子


Google实际上实现了他们自己的开源崩溃处理程序,名为,我想mozilla也会使用它(如果你想要更严重的东西——一个丰富而健壮的崩溃处理程序)。

你也可以在客户端系统上安装一个事后调试程序。当您的应用程序中没有内置转储创建时,这是一种体面的、通用的获取信息的方法(可能对于您仍然必须获取信息的旧版本)


可以通过运行来安装Windows上的Dr.Watson:
drwtsn32-i
运行
drwtsn32
(无任何选项)将打开配置对话框。这将允许创建崩溃转储文件,您可以稍后使用WinDbg或类似工具进行分析。

您可以使用它。您只需在代码中散布一些宏,它将收集堆栈跟踪,以及实际参数值、局部变量、循环计数器、,等等。它非常轻量级,因此可以保留在发布版本中,以便从最终用户机器上的崩溃中收集此信息

感谢关于gflags的信息,我从来都不知道它。我感觉此实用程序将在未来为我节省数月的工作:)当然——一旦我遇到任何类型的内存崩溃,我只是使用了页面堆功能——节省了很多时间。好吧,至少你可以看到哪个库调用导致了崩溃。在VS的中间窗口中,你可以键入“.load sos.dll”(不带引号)并使用sos调试器。描述如何计算堆栈跟踪。