【问题标题】:Getting line number from pdb in release mode在发布模式下从 pdb 获取行号
【发布时间】:2009-06-01 17:00:47
【问题描述】:

调试器(或 CLR 异常处理程序)是否可以使用 pdb 显示在发布模式下发生异常的行?

发布模式下的代码经过优化,并不总是遵循“原始”代码的顺序和逻辑。

令人惊讶的是,即使在发布模式下,调试器也可以逐步浏览我的代码。优化应该使导航非常不舒服。

能否请您为我澄清这两点?

【问题讨论】:

    标签: debugging line pdb-files


    【解决方案1】:

    我不太熟悉如何使用 CLR 完成此操作,但它可能与使用本机代码完成的方式非常相似。当编译器生成机器指令时,它会向 pdb 添加条目,基本上说“当前地址 X 处的指令来自 foo.cpp 中的第 25 行”。

    调试器知道当前正在执行的程序地址。因此它在 pdb 中查找某个地址 X,并发现它来自 foo.cpp 中的第 25 行。使用它,它能够“逐步”通过您的源代码。

    无论是 Debug 还是 Release 模式,这个过程都是相同的(前提是在 Release 模式下完全生成了一个 pdb)。但是,您是对的,由于优化,调试器通常在发布模式下不会“线性”地通过代码。它可能会意外跳到不同的行。这是由于优化器改变了指令的顺序,但它并没有改变地址到源行的映射,所以调试器仍然能够遵循它。

    【讨论】:

      【解决方案2】:

      [@Not Sure] 几乎是对的。 编译器尽最大努力识别与当前机器代码指令密切匹配的适当行号。

      PDB 和调试器对优化一无所知; PDB 文件本质上将机器代码中的地址位置映射到源代码行号。在优化的代码中,并不总是可以将汇编指令与特定的源代码行完全匹配,因此编译器会将其手头最接近的内容写入 PDB。这可能是“之前的源代码行”,或“封闭上下文(循环等)的源代码行”或其他内容。

      无论如何,调试器基本上会在 PDB 映射中找到最接近当前 IP(如“之前或等于”)的条目(指令指针)并突出显示该行。

      有时匹配不是很好,这时您会看到突出显示的区域到处乱跳。

      【讨论】:

      • 也许编译器会为发布和调试模式生成不同的 pdb。发布模式的pdb考虑了优化,所以它可以给出一个相对准确的异常行。
      • 哦,当然。 PDB 永远与构建它的 DLL(或 EXE)的完全相同的实例相关联。请注意,即使您在相同的模式下重新编译,没有任何源文件更改,您仍然无法混合和匹配 PDB 和 DLL。您的 PDB 必须与编译您正在调试的模块(DLL 或 EXE)时创建的完全相同,因为编译器可能会在每次构建时随机将内容放在不同的位置。那是你想要做的吗?
      • @Euro Micelli:> 编译器可能会在每次构建时随机将内容放在不同的位置
      • @Dan Moulding:我不同意。我不知道有任何标准要求编译器输出每次都 100% 相同。 [?] 只需要编译器输出一个“有效”的实现。 MS 链接器肯定会在每次构建时在 DLL 上应用不同的元数据(如构建时间戳)。在我早年的时候,我有一段 C++ 代码对静态初始化的顺序有隐藏的依赖;它每隔一次编译一次左右。不匹配的 PDB 可能“大​​部分”都能正常工作,但我确实见过不匹配的 PDB 在调试器中导致令人困惑的行为的情况。
      【解决方案3】:

      调试器会尽力猜测问题发生的位置。它不能保证 100% 准确,并且对于完全优化的代码,它通常会不准确 - 我发现不准确的地方从几行到完全错误的调用堆栈不等。

      调试器对优化代码的准确度实际上取决于代码本身以及您正在进行哪些优化。

      【讨论】:

      • 泰。 “有一个完全错误的调用堆栈。”堆栈跟踪不应该总是准确的?
      • 是否有关于行号的来源或更多信息?我在调试/pdb/编译器代码优化的SO上发红了一些帖子,发现没有明确的点。
      【解决方案4】:
      猜你喜欢
      • 2018-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-09
      • 2012-01-15
      • 1970-01-01
      • 2019-01-26
      相关资源
      最近更新 更多