代码之家  ›  专栏  ›  技术社区  ›  Eran

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

  •  5
  • Eran  · 技术社区  · 15 年前

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

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

    4 回复  |  直到 14 年前
        1
  •  7
  •   Michael    15 年前

    是的,优化的代码不太容易调试。不仅有些信息缺失,有些信息还会很容易误导。

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

    如果您有一个pdb,那么fpo不应该太影响可调试性,因为pdb包含展开fpo帧堆栈所需的所有信息。当使用需要不带符号进行堆栈跟踪的工具时,fpo可能是一个问题。对于许多项目来说,目前FPO的性能优势不超过诊断能力的影响;因此,MS决定不使用FPO优化构建Windows Vista。( http://blogs.msdn.com/larryosterman/archive/2007/03/12/fpo.aspx )

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

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

        2
  •  2
  •   MSN    15 年前

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

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

        3
  •  2
  •   SoapBox    15 年前

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

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

    还有一个常见的优化是执行“脏”堆栈帧(gcc中的foomit帧指针),这会导致代码不跟踪堆栈顶部。这很好,它为其他操作释放了一个额外的寄存器(x86上的ebp)。但这使得我们几乎不可能展开堆栈来看看到底发生了什么。这也使得在堆栈上几乎不可能找到局部变量和函数参数。

    一般来说:不要期望从“发布”构建中获得有用的调试信息。如果调试如此重要,即使是在发布时,那么您应该改为“发布”调试构建。

        4
  •  2
  •   paavo256    15 年前

    除了局部变量之外,“this”指针通常在优化的构建中被优化掉。有时可以通过在调用堆栈中向上移动足够多的对象指针或引用作为未优化的away变量存在的点来解决这一问题。

    一般来说。在优化的构建中单步执行通常或多或少会起作用,让我们看看代码做出了什么逻辑决策。检查这些决策所依据的数据通常要复杂得多。