PDB在调试时会给我什么,我如何知道它在工作?
我必须使用没有源代码的第三方组件。我有发布DLL和发布PDB文件。我们称之为" CorporateComponent.dll"。我自己的代码从此DLL创建对象,并在这些对象上调用方法。
CorpObject o = new CorpObject(); Int32 result = o.DoSomethingLousy();
调试时,方法'DoSomethingLousy'引发异常。 PDB文件对我有什么作用?如果它做的很好,我如何确定我正在使用它?
解决方案
回答
PDB是一个数据库文件,它将指令映射到原始代码中的行号,因此,当我们获得堆栈跟踪时,将获得代码的行号。如果它是非托管DLL,则PDB文件还将为我们提供堆栈跟踪中的函数名称,而该信息通常仅适用于不带PDB的托管DLL。
回答
我从pdb获得的主要内容是行号和堆栈跟踪的真实方法名称。
回答
pdb包含调试器正确读取堆栈所需的信息。堆栈跟踪将包含具有pdb的模块内部堆栈帧的行号和符号名称。
我将举两个用法示例。首先是显而易见的答案。第二部分解释了源索引的pdb。
第一种用法示例...
根据调用约定和编译器使用的优化,调试器可能无法通过我们没有pdb的模块手动展开堆栈。某些第三方库甚至操作系统的某些部分都可能发生这种情况。
考虑在Windows操作系统内部遇到访问冲突的情况。堆栈跟踪不会展开到我们自己的应用程序中,因为该OS组件使用特殊的调用约定,这会使调试器感到困惑。如果将符号路径配置为下载公共OS pdb的符号路径,则堆栈跟踪很有可能会展开到应用程序中。这样一来,我们就可以准确查看自己的代码将哪些参数传递给OS系统调用。 (以及第3方库内甚至我们自己的代码内的AV的类似示例)
第二用法示例...
Pdb具有另一个非常有用的属性,它们可以使用Microsoft称为"源索引"的功能与某些源控制系统集成。源索引的pdb包含源控制命令,这些命令指定如何从源控制中获取用于构建组件的确切文件版本。 Microsoft的调试器了解如何执行命令以在调试会话期间自动获取文件。这是一项功能强大的功能,可以使调试egineer免于必须手动将源树同步到给定构建的正确标签的麻烦。它对于远程调试会话和事后分析崩溃转储特别有用。
"用于Windows的调试工具"安装(windbg)包含一个名为srcsrv.doc的文档,该文档提供了一个示例,演示了如何使用srctool.exe确定在给定的pdb中哪些源文件在源索引中。
为了回答问题"我怎么知道",调试器中的"模块"功能可以告诉我们哪些模块具有相应的pdb。在windbg中,使用" lml"命令。在Visual Studio中,从调试菜单中的某个位置选择模块。 (抱歉,我没有Visual Studio的当前版本)
回答
为了在Visual Studio IDE中进行调试期间确认是否正在使用提供的PDB CorporateComponent.pdb,请查看输出窗口,并找到指示已加载CorporateComponent.dll的行,后跟字符串" Symbols loading"。
为了说明我的一个项目:
The thread 0x6a0 has exited with code 0 (0x0). The thread 0x1f78 has exited with code 0 (0x0). 'AvayaConfigurationService.vshost.exe' (Managed): Loaded 'C:\Development\Src\trunk\ntity\AvayaConfigurationService\AvayaConfigurationService\bin\Debug \AvayaConfigurationService.exe', Symbols loaded. 'AvayaConfigurationService.vshost.exe' (Managed): Loaded 'C:\Development\Src\trunk\ntity\AvayaConfigurationService\AvayaConfigurationService\bin\Debug\IPOConfigService.dll', No symbols loaded.
Loaded 'C:\Development\src...\bin\Debug\AvayaConfigurationService.exe', Symbols loaded.
这表明IDE调试器已找到并加载了PDB。
正如其他人指出的那样,在检查应用程序中的堆栈框架时,我们应该能够从CorporateComponent.pdb中看到符号。如果我们不这样做,那么也许第三方在发行版PDB构建中未包含符号信息。