是否有任何编译器选项可以使x64版本崩溃转储更有用?

时间:2014-12-31 10:54:34

标签: debugging visual-c++ visual-studio-2013 windbg

每当我为我的应用程序的x64版本构建获得崩溃转储时,我发现它很少见,我可以查看本地人,这使得修复某些问题变得困难或不可能。在x86中,我通常可以毫无问题地查看所有本地人。

发布版本中是否有任何编译器选项允许我在发布版本崩溃转储中查看本地?显然,我不想关闭优化,但也许有一些方法可以强制它来拯救当地人,对性能产生轻微影响?

1 个答案:

答案 0 :(得分:10)

你说过一些暗示为什么你不能看到当地人的事情......

#1 - 这是一个发布版本。

通过启用某些优化,编译器可以自由地做一些使本地人看起来更困难的事情。

  1. 它可以inline一个功能。发生这种情况时,未被优化的函数的本地与调用堆栈帧混合。
  2. 它可以使用名为Frame-Pointer Omission的技巧释放寄存器并在函数调用上保存几个时钟周期。
  3. 为了节省堆栈空间,编译器可以reuse the location在函数体中更早保存变量,以便稍后在函数中保存不同的变量。这意味着您在函数中的位置确定您实际上能够看到的本地人。
  4. #2 - 它是x64版本。

    MSVC对64位代码使用一种新的调用约定,称为x64 Calling Convention。前4个函数参数存储在寄存器中而不是堆栈中。这意味着即使您正在查看堆栈帧,您也不会看到某些参数,如果寄存器在您查看它们时已被重用于其他内容,您甚至可能无法恢复它们。


    那么,现在呢?

    现在我们知道你为什么会遇到这么困难的时候,让我们看看你能做些什么来解决上述问题。这些问题都没有真正表现出来,但它们共同努力使你的事情变得更加困难。

    1. 关闭一些优化。您可以尝试使用版本构建,其优化级别不会妨碍调试。您可能希望从上面提到的使用堆栈帧(/ Oy和/ Ob)的优化开始。那么你需要希望你仍然能够在关闭这些优化的情况下重现这个问题。此外,根据您的内部政策以及您与客户签订的合同,您可能需要在向客户发送非正式构建之前聘请律师 - 可能不是世界上最有趣的事情。

    2. 构建更好的符号文件。 VS2012及更高版本有一个新的编译器开关/d2Zi+ in VS2012/Zo in VS2013,可在启用优化时生成更好的调试信息。这使得调试优化代码与GCC / Clang相同。即使它在VS2012中没有记录,我仍然认为它非常安全,因为我看到生成的代码没有区别 - 只在符号文件中。您甚至可以使用此标志在本地重建并强制windbg通过.symopt+ 0x40使用新的符号文件。这使您有机会从已有的转储中获得更多。

    3. 使用windbg扩展来完成繁重工作。other StackOverflow answers中,我提到了一个名为CMKD的工具,它将我的培根保存了一对倍。除其他外,它尝试重新构建在寄存器中传递的x64调用约定中的参数。这不是一个确定的事情,但它可能是让他们回来的最好希望。

    4. 无论如何,我希望我的ramblings在你的调试中有用。