有时我的c ++程序在调试模式下崩溃,我得到的是一个消息框,说明某些内部内存管理例程中的断言失败(访问未分配的内存等)。但我不知道从哪里调用,因为我没有得到任何堆栈跟踪。如何获取堆栈跟踪或至少查看代码中的失败位置(而不是库/内置例程)?
答案 0 :(得分:7)
如果发生崩溃,无论是否有调试或发布版本,都可以获得有关崩溃发生位置的信息。即使您在没有源代码的计算机上,也可以看到调用堆栈。
要执行此操作,您需要使用使用EXE构建的PDB文件。将PDB文件放在与崩溃的EXE相同的目录中。注意:即使您拥有相同的源代码,构建两次并使用第一个EXE和第二个PDB也不起作用。您需要使用使用EXE构建的确切PDB。
然后将调试器附加到崩溃的进程。示例:windbg或VS。
然后只需检查您的调用堆栈,同时还打开线程窗口。您必须选择崩溃的线程并检查该线程的callstack。每个线程都有一个不同的调用堆栈。
如果您已经连接了VS调试器,它将自动转到导致崩溃的源代码。
如果崩溃发生在您正在使用的库中,那么您没有PDB。你无能为力。
答案 1 :(得分:3)
如果您在具有VS的计算机上运行调试版本,它应该提供它以便让您看到堆栈跟踪。
问题是真正的问题不再是在调用堆栈上了。如果你将指针释放两次,这可能会导致此问题与程序无关的其他地方(下次有任何访问堆数据结构时)
我在博客上写了一些提示,让问题显示在调用堆栈中,这样你就可以弄清楚发生了什么。
最好的建议是使用gflags实用程序使指针问题立即引起问题。
答案 2 :(得分:2)
您可以通过为未捕获的异常设置处理程序来触发小型转储。这是一个article,解释了所有关于小型转储的内容
谷歌实际上实现了他们自己的开源崩溃处理程序BreakPad,我也认为这也是mozilla使用的(如果你想要更严肃的东西 - 一个丰富而强大的崩溃处理程序)。
答案 3 :(得分:2)
This article描述了如何计算堆栈跟踪。
答案 4 :(得分:0)
如果我没记错的话,该消息框应该有一个“重试”按钮。然后,这应该在断言发生的那一刻打破程序(在调试器中)。
答案 5 :(得分:0)
CrashFinder可以帮助您找到DLL的异常位置以及报告的异常地址
您可以获取此代码并将其集成到应用程序中,以便在存在未捕获的异常时自动生成堆栈trage。这通常使用__try{} __except{}
或调用SetUnhandledExceptionFilter来执行,这允许您指定对所有未处理的异常的回调。
答案 6 :(得分:0)
您还可以在客户端系统上安装事后调试器。当您没有在应用程序中内置转储创建时,这是获取信息的一种不错的通用方法(对于您仍必须获取信息的旧版本)。
博士。可以通过运行来安装Windows上的Watson:drwtsn32 -i
运行drwtsn32
(不带任何选项)将打开配置对话框。这将允许创建崩溃转储文件,您可以稍后使用WinDbg或类似的东西进行分析。
答案 7 :(得分:-1)
您可以使用Poppy。您只需在代码中添加一些宏,它将收集堆栈跟踪,以及实际参数值,局部变量,循环计数器等。它非常轻量级,因此可以保留在发布版本中以从崩溃中收集此信息在最终用户机器上