Debugging 为什么不';t小型转储提供良好的调用堆栈?

Debugging 为什么不';t小型转储提供良好的调用堆栈?,debugging,callstack,minidump,dbghelp,Debugging,Callstack,Minidump,Dbghelp,多年来,我在许多游戏项目中使用了迷你转储,它们似乎有大约50%的机会拥有有效的调用堆栈。我能做些什么让他们拥有更好的呼叫栈 我已尝试将最新的dbghelp.dll放入exe目录。这似乎有些帮助 Visual Studio 2008或2010是否更好?(我仍然在VS2005上) 我使用的代码如下所示。调用堆栈中缺少什么?是否有一组地址不能解析为有效的函数名(即0x8732ae00而不是CFoo:Bar())?如果是这样,那么您需要将.pdb放在调试器可以找到它们的位置,或者在模块窗格的右键单击上下

多年来,我在许多游戏项目中使用了迷你转储,它们似乎有大约50%的机会拥有有效的调用堆栈。我能做些什么让他们拥有更好的呼叫栈

我已尝试将最新的dbghelp.dll放入exe目录。这似乎有些帮助

Visual Studio 2008或2010是否更好?(我仍然在VS2005上)


我使用的代码如下所示。

调用堆栈中缺少什么?是否有一组地址不能解析为有效的函数名(即0x8732ae00而不是CFoo:Bar())?如果是这样,那么您需要将.pdb放在调试器可以找到它们的位置,或者在模块窗格的右键单击上下文菜单中设置并设置“符号路径”

每次有人签入新的performe变更列表时,我们都会从每个二进制文件中存储每个.PDB,这样当办公室内的任何人或零售店的任何客户返回转储时,我们就有了与他们正在运行的游戏版本相对应的.PDB。设置了符号服务器和路径后,我所要做的就是双击.mdmp,它每次都能工作

或者您是否有一个调用堆栈,其中似乎只有一个函数?比如,0x8538cf00在堆栈中没有任何其他内容?如果是这样,那么崩溃实际上是堆栈本身被损坏。如果反向链中的返回地址已被覆盖,调试器自然将无法解析它们

有时您还会发现,实际发出minidump的线程并不是引发导致崩溃的异常的线程。在Threads窗口中查看其他线程中是否有一个线程包含了有问题的代码


如果您正在调试一个“发布”版本,也就是说,一个编译时打开了所有优化标志的版本,那么您将不得不接受这样一个事实,即调试器在查找局部变量和其他一些数据时会遇到困难。这是因为启用优化意味着允许编译器将数据保留在寄存器上、折叠计算,并通常执行各种各样的操作,以防止数据实际写入堆栈。如果这是您的问题,那么您需要打开反汇编窗口并手动跟踪数据,或者重新生成调试二进制文件并在您可以查看的地方重现问题。

我不使用迷你转储,而是将堆栈“手动”转储到日志文件中 (见和) )


我遇到了与您类似的行为:有时存在有效的调用堆栈,有时没有。在少数情况下,堆栈可能确实损坏。在所有情况中,可能有1/3的情况下根本不会调用已安装的异常处理程序!我猜这在某种程度上是windows结构化异常处理的问题。

如果需要堆栈转储,请关闭帧指针优化。帧指针用于显式定义堆栈帧。如果没有它们,调试器必须推断出每个帧的位置。

要提高转储中调用堆栈的准确性,可以做的一件事是使用Visual Studio以外的调试器——具体地说,使用WinDbg或使用dbgeng.dll中的“Windows debugger”调试引擎的另一个工具(与Visual Studio使用的“Visual Studio调试器”调试引擎)

根据我们的经验,WinDbg在从Visual Studio生成不可用或极不准确的调用堆栈的相同转储生成良好的调用堆栈方面是100%可靠的。从我所知,在未处理的异常是崩溃源的情况下,WinDbg会自动执行,但Visual Studio不会(或不能?).两个调试器使用

WinDbg一开始可能会让人望而生畏,所以下面是我的快速指南,介绍如何使它更容易使用,甚至避免直接使用它

提取好的调用堆栈的普通指南

这些顺序从“最快/最容易”到“最慢/最难解释”

  • 最简单的选项:使用
  • 这是一个鲜为人知的工具,它自动化了许多常见问题的分析,非常简单,可以提供给非程序员甚至客户。它速度快,几乎万无一失,已经成为我快速分析即将到来的崩溃转储的“转到”工具

    • 启动“DebugDiag分析”应用程序
    • 选择主页面上的“CrashHangAnalysis”复选框
    • 将转储文件拖放到主页上的“数据文件”窗格中
    • 单击“开始分析”

    几秒钟到几分钟后,它将弹出一个漂亮的.mhtml文件,其中包含问题分析、所有相关线程的信息、完整的调用堆栈等。所有这些都是超链接的,易于使用

    DebugDiag甚至可以自动执行一些更复杂的分析,这在WinDbg中是可能的,但很痛苦(比如跟踪应用程序中350个线程中的哪个线程导致死锁)

    注意:由于安全原因,Chrome不会下载或打开.mhtml文件,因此必须在Internet Explorer或Microsoft Edge中打开才能使用。这很烦人,我已经向DebugDiag团队提出了请求(dbgdiag@microsoft.com)将格式更改为纯HTML

  • 中间选项:将WinDbg安装为Visual Studio的备用调试引擎
    • 如果尚未安装Visual Studio,请安装它。这需要在下一步之前完成
    • 安装
    • 启动Visual Studio,然后(这一部分很重要!)使用新的“文件->打开->崩溃转储…”选项打开转储。这将使用Windows调试器调试崩溃转储(如果您改为在Visual Studio上拖放转储或使用标准的“文件->打开->文件…”。。。“选项打开转储,它将使用旧的Visual Studio调试引擎进行调试…因此请小心使用正确的选项)
    • 现在,您应该能够看到正确的调用堆栈,并使用VisualStud进行导航
      !vc7fpo - toggles some of the windbg heuristics.
      !stackdbg d, 7, f - turns on windbg stack walk
      k1 - walks one level of the stack, spitting diagnostics as controlled by !stackdbg
      dds esp - dumps the raw contents of the stack, doing a symbol lookup on each pointer