Debugging 在释放模式下从pdb获取行号

Debugging 在释放模式下从pdb获取行号,debugging,line,pdb-files,Debugging,Line,Pdb Files,调试器(或CLR异常处理程序)是否可以使用pdb在发布模式下显示异常发生的行 在发布模式下,代码经过优化,并不总是遵循“原始”代码的顺序和逻辑 同样令人惊讶的是,调试器可以一步一步地浏览我的代码,即使是在发布模式下。优化应该使导航非常不方便 您能为我澄清这两点吗?调试器尽最大努力猜测问题发生的位置。它不能保证100%准确,而且对于完全优化的代码,它通常是不准确的——我发现不准确的地方从几行到完全错误的调用堆栈 调试器使用优化代码的准确度实际上取决于代码本身以及您正在进行的优化。我不太熟悉如何使用

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

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

同样令人惊讶的是,调试器可以一步一步地浏览我的代码,即使是在发布模式下。优化应该使导航非常不方便


您能为我澄清这两点吗?

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


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

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

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


无论是调试模式还是发布模式(只要在发布模式下生成pdb),此过程都是相同的。但是,您是对的,通常在发布模式下,由于优化,调试器不会“线性”地遍历代码。它可能会意外地跳转到不同的行。这是由于优化器更改了指令顺序,但它没有更改地址到源代码行的映射,因此调试器仍然能够遵循它。

请参考以下so问题:


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

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

不管怎样,调试器基本上会在PDB映射中找到最接近当前IP(指令指针)的条目(如“before或equal”),并高亮显示该行


有时比赛不太好,这时你会看到突出显示的区域到处乱跳。

Ty。“有一个完全错误的调用堆栈。”堆栈跟踪不应该总是准确的?行号上是否有来源或更多信息?我在调试/pdb/编译器代码优化等方面发了一些帖子,但没有找到明确的观点。也许编译器会为发布和调试模式生成不同的pdb。发布模式的pdb考虑了优化,因此它可以为异常提供相对准确的线路。哦,绝对正确。PDB永远与构建它的DLL(或EXE)的同一个实例绑定。请注意,即使在没有任何源文件更改的情况下以相同的模式重新编译,也无法混合和匹配PDB和DLL。您的PDB必须与编译您正在调试的模块(DLL或EXE)时创建的PDB完全相同,因为编译器可能会在每个构建中随机将内容放在不同的位置。这就是你想要做的吗?@Euro-neucoli:>编译器可能会在每个构建中随机地将内容放在不同的位置。<这听起来像是灾难的秘诀。我在实践中从未见过这样的事情。这是不是只有使用Microsoft工具才会发生的事情?还是.NET?在我使用过的每个实例中,编译器总是从给定的输入生成完全相同的逐位结果。其他任何东西都会被高度怀疑(你能说“不可生产的构建”?)@Dan Moulding:我不同意。我不知道有任何标准要求编译器每次输出都100%相同。编译器[?]仅用于输出“有效”实现。MS链接器肯定会在每次生成时在DLL上应用不同的元数据(如生成时间戳)。在我早期,我有一段C++代码,它隐藏了对静态初始化顺序的依赖;大约每隔一次编译,它只工作一次。不匹配的PDB可能“大部分”工作,但我确实看到过不匹配的PDB在调试器中导致令人困惑的行为的情况。