在发布版本中有任何编译器选项可以让我在崩溃转储中查看本地变量吗?显然,我不想关闭优化,但也许有一些方法可以强制它保存本地变量并带来较小的性能影响吗?
您提到了几个原因,解释了为什么您无法查看局部变量:
#1 - 这是一个发布版本。
当启用某些优化时,编译器可以执行一些使查看局部变量更加困难的操作:
#2 - 这是一个x64版本。
MSVC对于64位代码使用新的调用约定,称为x64调用约定。前4个函数参数存储在寄存器中,而不是堆栈上。这意味着即使您正在查看一个堆栈帧,您也不会看到其中一些参数,如果寄存器已被重新用于其他变量,则可能无法恢复它们。
那么现在怎么办?
既然我们知道了为什么您会遇到这样的困难,让我们看看您可以采取哪些措施来解决上述问题。以上所有问题都不是致命问题,但它们共同使得对局部变量的查看变得更加困难。
关闭一些优化。 您可以尝试使用启用了某些不会对调试造成太大影响的优化级别的发布版本构建。您可能希望从上面提到的与堆栈帧 (/Oy 和 /Ob) 相关的优化开始尝试。然后,您需要希望在关闭这些优化的情况下仍然能够重现该问题。此外,根据您内部政策和与客户的合同,您可能需要在向客户发送非官方版本之前请律师参与--这可能不是世界上最有趣的事情。
生成更好的符号文件。 VS2012 及更高版本具有一个新的编译器开关,/d2Zi+ in VS2012 和 /Zo in VS2013, 当启用优化时会生成更好的调试信息。这使得调试优化代码与 GCC/Clang 相当。即使在 VS2012 中未记录该选项,但我仍然认为它相当安全,因为我没有看到生成的代码有任何差异——只有符号文件不同。您甚至可以使用 .symopt+ 0x40
强制 windbg 使用您的新符号文件,这使得您有更多机会从已有的转储文件中获取更多信息。
使用Windbg扩展来进行繁重的工作。在其他StackOverflow答案中,我提到了一个称为CMKD的工具,它救过我几次。它可以尝试重构以寄存器传递的x64调用约定中传递的参数等内容。虽然不是百分之百可靠,但这可能是找回参数的最佳希望。
无论如何,我希望我的胡言乱语能对您的调试有所帮助。
g++
或者clang
并加上-O2 -g
参数)。 - Basile Starynkevitch