Chr*_*ine 25
为提高转储中调用堆栈的准确性,您可以做的一件事是使用Visual Studio以外的调试器 - 特别是使用WinDbg或使用dbgeng.dll中的"Windows Debugger"调试引擎的其他工具(相反)到Visual Studio使用的"Visual Studio Debugger"调试引擎.
根据我们的经验,WinDbg在从Visual Studio生成无法使用或非常不准确的调用堆栈的相同转储中生成良好的调用堆栈方面100%可靠.据我所知,在未处理异常是崩溃源的情况下,WinDbg会自动执行重构/恢复异常调用堆栈的棘手过程,但Visual Studio却没有(或不能?).两个调试器使用不同的启发式来解释堆栈
WinDbg起初可能令人生畏,所以这里是我的快速指南,介绍如何让它更容易,甚至避免直接使用它.
一个纯粹致命的指南,以提取良好的callstacks
这些是从"最快/最简单"到"最慢/最神秘的解释"的排序.
最简单的选择:使用Microsoft的DbgDiag
这是一个鲜为人知的工具,可以自动对常见问题进行大量分析,而且非常简单,可以给非程序员甚至客户.它快速且几乎万无一失,并且已成为我快速分析传入故障转储的"转到"工具.
几秒钟到几分钟后,它会吐出一个漂亮的.mhtml文件,其中包含对问题的分析,有关所有相关线程的信息,完整的调用堆栈等.所有超链接和易于使用.
DebugDiag甚至可以自动执行一些更复杂的分析,这些分析可能在WinDbg中很痛苦(比如跟踪应用程序中350个线程中的哪一个导致死锁).
注意:出于安全原因,Chrome不会下载或打开.mhtml文件,因此您必须在Internet Explorer或Microsoft Edge中打开才能使用它.这很烦人,我已经向DebugDiag团队(dbgdiag@microsoft.com)提交了一个请求,要求将格式更改为纯HTML
中间选项:安装WinDbg作为Visual Studio的备用调试引擎
硬核选项:直接使用WinDbg
!analyze -v,然后按Enter.经过一段时间后,WinDbg会吐出一个崩溃调用堆栈,并且还会估计出问题的根源.如果你正在分析一个死锁,你可以试试!analyze -v -hang,WinDbg会经常向你展示所涉及的依赖链.
此时您可能拥有所需的所有信息!但是,如果您希望在Visual Studio调试器中检查进程状态,则可以执行以下附加步骤:
注意:以上所有内容都要求配置正确的符号服务器路径,否则您将无法解析调用堆栈中的符号.我建议设置_NT_SYMBOL_PATH环境变量,以便它可以自动用于Visual Studio,WinDbg和DebugDiag.
你的callstack缺少什么?你有一堆地址没有解析为有效的函数名称(即0x8732ae00而不是CFoo:Bar())?如果是这样,那么您需要将.PDB放在调试器可以找到它们的位置,或者设置符号服务器并在"模块"窗格的右键单击上下文菜单中设置"符号路径".
每当有人检查新的Perforce更改列表时,我们会存储每个二进制文件中的每个.PDB,这样当转储从办公室内的任何人或零售的任何客户回来时,我们都会得到与他们所在游戏版本相对应的.PDB.运行.设置符号服务器和路径后,我所要做的就是双击.mdmp,每次都可以使用.
或者你有一个似乎只有一个功能的调用堆栈?比如,0x8538cf00在堆栈中没有任何其他东西?如果是这样,那么你的崩溃实际上是堆栈本身被破坏了.如果后交链中的返回地址已被覆盖,则调试器自然无法解析它们.
有时您也会发现实际发出minidump的线程不是引发导致崩溃的异常的线程.在Threads窗口中查看其中一个其他线程是否包含违规代码.
如果您正在调试"发布"版本 - 也就是说,编译了所有优化标志的编译器 - 您将不得不忍受调试器在查找局部变量和其他一些数据时遇到的问题.这是因为启用优化意味着允许编译器将数据保存在寄存器上,折叠计算,并且通常会执行各种阻止数据实际写入堆栈的事情.如果这是您的问题,那么您需要打开反汇编窗口并手动追踪数据,或重建调试二进制文件并重现问题,您可以在其中查看它.