优化是否会影响使用其PDB调试VC ++应用程序的能力?

时间:2009-02-18 21:54:14

标签: c++ visual-studio optimization pdb-files

为了能够正确调试发布版本,需要一个PDB文件。当编译器使用不同类型的优化(FPO,PGO,内部函数,内联等)时,PDB文件是否会变得不太可用?如果是这样,优化效果是否严重或仅仅导致相邻的代码行混淆?

(我使用的是VC2005,并且总是选择可调试性而非优化性能 - 但问题是一般的)

4 个答案:

答案 0 :(得分:7)

是的,优化的代码可调试性较差。不仅缺少一些信息,一些信息也会产生误导。

我认为最大的问题是局部变量。编译器可以使用相同的堆栈地址或在整个函数中注册多个变量。正如其他海报所提到的,有时甚至会弄清楚“这个”指针是什么可能需要一些时间。调试优化代码时,您可能会看到当前行在单步执行时跳转,因为编译器重新组织了生成的代码。如果你使用PGO,这种跳跃可能会变得更糟。

如果您有PDB,FPO不应过多影响可调试性,因为PDB包含为FPO帧展开堆栈所需的所有信息。使用需要在没有符号的情况下获取堆栈跟踪的工具时,FPO可能会出现问题。对于许多项目而言,如今FPO的性能优势并不超过对可诊断性的影响;出于这个原因,MS决定不使用FPO优化(http://blogs.msdn.com/larryosterman/archive/2007/03/12/fpo.aspx)构建Windows Vista。

我更喜欢调试未优化的代码,但这并不总是可行的 - 一些问题只能用优化的代码重新编写,客户崩溃转储来自已发布的版本,并且有时无法部署调试私有代码。通常在调试优化代码时,我使用反汇编视图 - dissasembly never lies。

这一切都适用于windbg,因为我使用它进行所有本机代码调试。 Visual Studio的调试器可能会更好地处理其中一些情况。

答案 1 :(得分:2)

是。它有时可能很严重,尽管这通常更多是内联或重新排序代码的结果。

局部变量也可能无法在监视窗口中准确显示,因为它们可能只存在于寄存器中,并且在切换堆栈帧时可能无法正确显示。

答案 2 :(得分:2)

优化会严重影响任何平台上的调试(不仅仅是VC的PDB文件)。

正是由于你提到的原因,函数内联在某些情况下可能会完全混淆哪些指令属于哪个函数(因为有时它们属于两者)。

另一个常见的优化是执行“脏”堆栈帧(GCC中的-fomit-frame-pointer),这会导致代码无法跟踪堆栈顶部。这很好,它为其他操作释放了额外的寄存器(x86上的ebp)。但它几乎不可能解开堆栈以查看实际发生的情况。它也几乎不可能在堆栈上找到局部变量和函数参数。

一般情况下:不要期望从“发布”版本中获取有用的调试信息。如果调试很重要,即使在发布时也是如此,那么你应该“释放”调试版本。

答案 3 :(得分:2)

除了局部变量之外,'this'指针通常在优化的构建中进行优化。这有时可以通过在调用堆栈中向上移动到对象指针或引用作为未优化的变量存在的点来解决。

总的来说。优化构建中的单步执行通常或多或少地工作,并让人们看到代码所做的逻辑决策。检查这些决策所依据的数据通常要复杂得多。