我已经使用在许多游戏项目多年来的小型转储,他们似乎有关于有一个有效的调用堆栈的几率为50%。 我能做些什么,让他们有更好的调用栈?
我试图把最新的dbghelp.dll的exe文件目录。 这似乎有些帮助。
为Visual Studio 2008或2010的更好吗? (我仍然在VS 2005)。
我使用的代码看起来像这个样 。
我已经使用在许多游戏项目多年来的小型转储,他们似乎有关于有一个有效的调用堆栈的几率为50%。 我能做些什么,让他们有更好的调用栈?
我试图把最新的dbghelp.dll的exe文件目录。 这似乎有些帮助。
为Visual Studio 2008或2010的更好吗? (我仍然在VS 2005)。
我使用的代码看起来像这个样 。
有一两件事可以做,以提高调用栈的垃圾堆中发现的准确性是使用比Visual Studio的其他调试器 - 具体而言,使用WinDbg,或者使用“Windows调试”在dbgeng.dll发现调试引擎的另一个工具(而不是到Visual Studio中使用“Visual Studio调试器”调试引擎)。
根据我们的经验,WinDbg的是从那里Visual Studio中产生不可用或非常不准确的调用栈相同堆放产生良好的调用栈100%可靠。 从我可以告诉,在未处理的异常是飞机失事的源WinDbg的自动执行的情况下重建/恢复异常调用堆栈的棘手的过程 ,但Visual Studio不会(或不能?)。 这两个调试器使用不同的启发式解释堆栈
WinDbg中首先可以是艰巨的,所以这里是我如何使它更容易,甚至避免直接使用它快速指南。
一个凡人指南要提取良好的调用堆栈
这些都是从“最快/最简单的”到“最慢/最神秘的解释”命令。
最简单的方法:使用微软DbgDiag
这是一个鲜为人知的工具,它可以自动很多常见问题的分析,这是很简单的给非程序员甚至客户。 它的快速和几乎万无一失,并已成为快速分析传入的崩溃转储我“去”的工具。
几秒钟到几分钟后,它会吐出含有对问题的分析一个很好的.mhtml文件,信息有关的所有相关的线程,完整的调用栈等所有超链接,易于使用。
DebugDiag资料,甚至自动执行一些更复杂的分析,这是可能的,但痛苦的在WinDbg中(如追踪其在应用程序中的350个线程负责死锁)的。
注:Chrome浏览器不会下载或打开文件.mhtml出于安全考虑,所以你必须在Internet Explorer或Microsoft边缘打开它是可用的。 这是烦人,我已经提交给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资料。
什么是您的调用堆栈缺少什么? 你有一大堆的地址不解析为有效的函数名(0x8732ae00的即不是Cfoo的:酒吧())? 如果是这样,那么你需要的是把你的.PDBs您的调试器可以找到他们,或者建立一个符号服务器 ,并设置了“符号路径”,在模块窗格中右键单击快捷菜单。
我们每天.PDB存储从每个二进制每次有人检查一个新的Perforce变更列表,这样,当转储从办公室或零售客户的任何内部人回来的时候,我们必须对应于他们的游戏版本中.PDB运行。 与符号服务器和路径设置,所有我需要做的仅仅是双击.mdmp和它的作品每一次。
还是你有,似乎只有一个功能它调用堆栈? 像,0x8538cf00没有任何东西在它上面的堆栈? 如果是这样,那么你的崩溃实际上是栈本身被损坏。 如果backchain的返回地址已被覆盖,自然调试器将无法加以解决。
有时还你会发现,实际上发出转储线程不会抛出导致崩溃的例外之一。 期待中的线程窗口,看看其他线程的一个有问题的代码在里面。
如果您正在调试一个“放”的构建 - 也就是说,一个与开启所有优化标志编译 - 你将不得不面对这一事实,调试器就很难找到本地变量和其他一些数据。 这是因为打开优化是指允许编译器保持对寄存器中的数据,计算塌陷,一般做各种各样的事情,防止过实际写入到堆栈的数据。 如果这是你的问题,那么你就需要打开反汇编窗口,并用手追逐的数据,或者重建一个调试二进制并重现该问题,你可以看看它。
关闭帧指针优化,如果你需要的堆栈转储。 帧指针被用来明确定义堆栈帧。 如果没有他们,调试器必须根据每一帧的位置。
记录转储的代码是不太可能相关。 一个小型转储记录模块的信息(用于获取符号)主要的事情和所有线程堆栈的全部内容。 除此之外,基本信息(总是记录)没有别的事。
获得良好的符号(包括PE文件)是堆栈行走的关键。 更多详细信息可以在这里找到: https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/
我发现,Visual Studio是通常显示调用堆栈可靠。 它会自动从显示异常记录相关的调用堆栈,它使容易改变线程,这样就可以看到所有线程的调用堆栈。 它有时试图“隐藏”的细节它认为可能混淆你 - 不管是好是坏取决于你的技能水平。
WinDbg中默认显示的是记录的崩溃转储,而不是崩溃调用堆栈的代码的调用堆栈。 WinDBG的需要你去“.ecxr”或‘!分析-v’才能看到崩溃堆栈。 我觉得这样不方便。 WinDbg中还需要更多的配置,以很有用。
这两个调试器确实有不同的堆栈行走启发。 需要这些启发式,举例来说,如果你打电话或返回地址零,因为没有该地址没有展开信息。 对于“干净”崩溃,其中失败的指令是在正常的代码这些试探不太重要。
堆栈行走已经在过去的十年里几乎肯定提高。 2015年VS社区版是非常有能力而且是免费的,所以您不妨试试。
如果您使用WinDbg,那么你可以尝试一些实验:
!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
如果升级到2015年VS仍然有问题,那么很可能是堆栈行走故障是特定于您所看到的崩溃。 如果缓冲区溢出崩溃然后调用堆栈之前tromps堆栈将不可挽回地损害。 你的问题有关于你所看到的给出一个明确的诊断是什么故障信息太少。 我觉得这两个调试器相当可靠的堆栈显示器,但我通常也明白为什么他们有时会失败,这时我仍然可以提取我需要的信息。
我不使用小型转储,而是倾倒德栈由“手”到一个日志文件(见www.ddj.com/cpp/185300443和如何登录栈帧与Windows 64 )。
我遇到类似的行为像你这样:有时候有一个有效的调用堆栈,有时候没有。 病例较少数量的堆栈可能真的损坏。 在所有的情况下,也许1/3的安装异常处理程序不叫了! 我想,它在某种程度上窗户的问题结构化异常处理。