在 Visual Studio 调试器中指定符号(.pdb)和源文件(C#、C++、Visual Basic、F#)

程序数据库 (.pdb) 文件(也称为符号文件、映射项目的源代码中的标识符和语句)到已编译应用中的相应标识符和说明。 这些映射文件将调试器链接到源代码,从而启用调试。

使用标准调试生成配置从 Visual Studio IDE 生成项目时,编译器会创建相应的符号文件。 本文介绍如何在 IDE 中管理符号文件,例如:

有关符号文件的详细说明,请参阅以下内容:

符号文件的工作原理

.pdb 文件保存调试和项目状态信息,允许对应用的调试配置进行增量链接。 Visual Studio 调试器使用 .pdb 文件在调试时确定两个关键信息片段:

  • 要在 Visual Studio IDE 中显示的源文件名和行号。
  • 在应用中停止的断点位置。

符号文件还显示源文件的位置,还可以选择显示要从中检索它们的服务器。

调试器仅加载与应用构建时创建的 .pdb 文件完全匹配的 .pdb 文件(即原始 .pdb 文件或其副本)。 此确切重复是必需的,因为即使代码本身没有更改,应用布局也会更改。 有关详细信息,请参阅 为什么 Visual Studio 要求调试器符号文件与生成的二进制文件完全匹配?

小窍门

若要在项目源代码外部调试代码(如 Windows 代码或项目调用的第三方代码),必须指定外部代码的 .pdb 文件(以及(可选)源文件的位置,这些文件必须与应用中的生成完全匹配。

调试器搜索符号的地方

在 Visual Studio IDE 中调试项目时,调试器会自动加载默认情况下可以找到的符号文件。

注释

在远程设备上调试托管代码时,所有符号文件必须位于本地计算机上,或位于 调试器选项中指定的位置。

调试器在以下位置搜索符号文件:

  1. 项目文件夹。

  2. DLL 或可执行文件 (.exe) 文件中指定的位置。

    默认情况下,如果在计算机上生成 DLL 或 .exe 文件,链接器会将关联的 .pdb 文件的完整路径和文件名放在 DLL 或 .exe 文件中。 调试器检查符号文件是否存在于该位置。

  3. 与 DLL 或 .exe 文件相同的文件夹。

  4. 符号文件的调试器选项中指定的任何位置。 若要添加和启用符号位置,请参阅 “配置符号位置和加载选项”。

    • 任何本地符号缓存文件夹。

    • 指定的网络、Internet 或本地符号服务器和位置,例如 Microsoft 符号服务器(如果选择)。 Visual Studio 可以从实现协议的 symsrv 符号服务器下载调试符号文件。 Visual Studio Team Foundation ServerWindows 调试工具 是两种可以使用符号服务器的工具。

      可以使用的符号服务器包括:

      公共Microsoft符号服务器:若要调试调用系统 DLL 或第三方库期间发生的崩溃,通常需要系统 .pdb 文件。 系统 .pdb 文件包含 Windows DLL、 .exe 文件和设备驱动程序的符号。 可以从公共Microsoft符号服务器获取 Windows作系统、MDAC、IIS、ISA 和 .NET 的符号。

      内部网络或本地计算机上的符号服务器:团队或公司可以为自己的产品创建符号服务器,并作为来自外部源的符号的缓存。 你可能自己的计算机上有一个符号服务器。

      第三方符号服务器:Windows 应用程序和库的第三方提供程序可以提供对 Internet 上的符号服务器的访问权限。

警告

如果使用非公共Microsoft符号服务器的符号服务器,请确保符号服务器及其路径可信。 由于符号文件可能包含任意可执行代码,因此你可能会暴露在安全威胁之中。

配置符号文件和加载选项的位置

默认情况下,调试器会检查各种位置中的符号。 请参阅 调试器查找符号的位置

“工具>选项>调试>符号 ”页上,可以:

  • 指定并选择符号文件的搜索路径。
  • 为Microsoft、Windows 或第三方组件指定符号服务器。
  • 指定你执行或不希望调试器自动加载符号的模块。
  • 在主动调试时更改这些设置。 请参阅调试时加载符号

若要指定符号位置和加载选项,请执行以下作:

注释

这些选项已在 Visual Studio 2022 版本 17.12 预览版 1 中更新。

  1. 在 Visual Studio 中,打开 工具>选项>调试>符号 (或 调试>选项>符号)。

  2. 在“符号文件(.pdb)位置”下

    • 若要使用 Microsoft符号服务器NuGet.org 符号服务器,请选中该复选框。

    • 若要添加新符号服务器位置,请执行以下步骤:

      1. 选择 + 工具栏中的符号。
      2. 在文本字段中键入符号服务器或符号位置的 URL(http)、网络共享或本地路径。 语句结束有助于找到正确的格式。

    工具 - 选项 - 调试 - 符号页

    工具 - 选项 - 调试 - 符号页

    注释

    仅搜索指定的文件夹。 必须为要搜索的任何子文件夹添加条目。

    • 若要添加新的 Azure DevOps 符号服务器位置,请执行以下操作:

      1. 选择工具栏中的 工具/选项/调试/符号新服务器图标 图标。

      2. “连接到 Azure DevOps 符号服务器 ”对话框中,选择一个可用的符号服务器,然后选择“ 连接”。

        有关详细信息,请参阅 “添加 Azure Artifacts 符号服务器”。

    • 若要更改符号位置的加载顺序,请使用 Ctrl+向上键和 Ctrl向下+或向上键和向下箭头图标。

    • 若要编辑 URL 或路径,请双击该条目,或将其选中并按 F2

    • 若要删除某个条目,请选择该条目,然后选择 - 图标。

  3. (可选)若要提高符号加载性能, 请在此目录中的缓存符号下,键入符号服务器可复制符号到的本地文件夹路径。

注释

不要将本地符号缓存放置在受保护的文件夹中,如 C:\Windows 或子文件夹。 而应使用可读写的文件夹。

注释

如果设置了 _NT_SYMBOL_PATH 环境变量,它将覆盖 在此目录中的缓存符号下设置的值。

  1. 指定您希望调试器在启动时从 符号文件 (.pdb) 位置 加载的模块。

    • 选择“ 自动选择要搜索的模块符号 ”(建议)以允许 Visual Studio 决定要搜索和加载哪些符号。 默认情况下,Visual Studio 会自动加载由打开的解决方案生成的符号,并加载执行常见调试作所需的任何其他符号。 这减少了 Visual Studio 必须搜索和加载的文件数,从而提高调试器性能。 可以通过单击 “指定模块筛选器 ”链接来强制加载其他符号。

    • 选择“搜索所有模块符号”,除非排除以强制 Visual Studio 加载调试过程中的所有符号。 不建议这样做,因为它可能会降低调试体验的速度。 如果选择此选项,可以通过单击 “指定模块筛选器 ”链接来强制 Visual Studio 忽略某些符号。

    • 选择“加载所有模块”(除非已排除(默认值),以加载符号文件位置中所有模块的所有符号,但专门排除的模块除外。 若要排除某些模块,请选择 “指定排除的模块”,选择 + 图标,键入要排除的模块的名称,然后选择“ 确定”。

    • 若要仅加载从符号文件位置指定的模块,请选择 “仅加载指定的模块”。 选择 “指定包含的模块”,选择 + 图标,键入要包括的模块的名称,然后选择“ 确定”。 不会加载其他模块的符号文件。

  2. 选择“ 确定”。

指定模块筛选器

“自动选择要搜索的模块符号”“除非排除,否则搜索所有模块符号”的选项使您可以更精细地控制调试时要搜索哪些符号。 选择 “指定模块筛选器 ”以微调体验。

默认情况下,当 “自动选择要搜索的模块符号 ”处于选中状态时,会看到以下对话框:

指定模块筛选器的屏幕截图。

可以使用“+”图标将模块添加到筛选器。 模块筛选器支持简单的通配符匹配。 “*”匹配任意组字符。 例如,“*myproduct*”将匹配“myproduct.utilities.dll”和“entrypoint.myproduct.exe”等文件。

还有几种其他选项可以进一步自定义体验:

  • 始终加载位于模块旁边的符号 ,指示 Visual Studio 加载存储在文件系统中的 pdb 文件,这些文件位于其相应的 .dll 或 .exe 文件旁边。 例如,尝试调试已部署的 Web 应用时,这非常有用。

  • 在需要时自动加载其他符号 ,指示 Visual Studio 搜索符号以执行常见的调试作,例如单步执行,即使要单步执行的模块不在项目或模块筛选器中。 确定搜索的方式可能会受到“仅我的代码”设置的影响。

如果您选择了“搜索所有模块符号,除非排除”,则模块筛选器对话框如下所示:

指定排除的模块的屏幕截图。

在此对话框中,可以选择 不希望 Visual Studio 加载符号的模块。 在这种情况下,Visual Studio 会尝试为正在调试的进程中的每个模块(包括第三方模块)加载符号,除非您添加匹配的筛选器来排除它们。 修改此行为的唯一其他方法是通过“仅我的代码”设置。

用于调试的其他符号选项

可以在工具>选项>调试>常规(或调试>选项常规)中选择其他符号选项>:

  • 加载 dll 导出(限本地)

    加载 C/C++的 DLL 导出表。 有关详细信息,请参阅 DLL 导出表。 读取 DLL 导出信息涉及一些开销,因此默认情况下会关闭加载导出表。 也可以在 C/C++生成命令行中使用 dumpbin /exports

  • 启用地址级调试 并且在源不可用时显示反汇编

    无法找到源或符号文件时,始终显示反汇编。

    选项/调试/常规反汇编选项

  • 启用源服务器支持

    当本地计算机上没有源代码或 .pdb 文件与源代码不匹配时,使用源服务器来帮助调试应用。 源服务器接受对文件的请求,并从源代码管理返回实际文件。 源服务器使用名为 srcsrv.dll 的 DLL 运行,以读取应用的 .pdb 文件。 .pdb 文件包含指向源代码存储库的指针,以及用于从存储库检索源代码的命令。

    可以通过在名为 srcsrv.ini的文件中列出允许的命令来限制 srcsrv.dll 可从应用的 .pdb 文件中执行的命令。 将 srcsrv.ini 文件放置在 与srcsrv.dlldevenv.exe相同的文件夹中。

    重要

    任意命令可以嵌入到应用的 .pdb 文件中,因此请确保仅将要执行的命令放入 srcsrv.ini 文件中。 任何尝试执行不在 srcsvr.ini 文件中的命令都会导致出现确认对话框。 有关详细信息,请参阅 安全警告:调试器必须执行不受信任的命令

    不会对命令参数执行验证,因此请谨慎使用受信任的命令。 例如,如果在srcsrv.ini中列出了 cmd.exe ,恶意 用户可能会在 cmd.exe 上指定参数,使其变得危险。

    选择此项和所需的子项。 允许源服务器用于部分信任程序集(仅托管)始终运行不受信任的源服务器命令,而无需提示 可能会增加安全风险。

    “启用源服务器”选项

编译器符号选项

使用标准 调试 生成配置从 Visual Studio IDE 生成项目时,C++托管编译器会为代码创建相应的符号文件。 还可以在代码中设置编译器选项。

若要在 Visual Studio 中设置生成配置的编译器选项,请参阅 “设置调试和发布配置”。

.NET 选项

使用 /debug 构建以生成 .pdb 文件。 可以使用 /debug:full/debug:pdbonly 生成应用程序。 使用 /debug:full 生成可调试代码。 使用 /debug:pdbonly 进行生成可以生成 .pdb 文件,但不会生成通知 JIT 编译器调试信息可用的 DebuggableAttribute。 如果要为不希望调试的发布版本生成 .pdb 文件,请使用 /debug:pdbonly。 有关详细信息,请参阅 /debug(C# 编译器选项)/debug (Visual Basic)。

C/C++ 选项

  • VC<x>.pdb<project>.pdb 文件

    使用 /ZI 或 /Zi 生成时,会创建用于 C/C++的 .pdb 文件。 在 Visual C++中, /Fd 选项命名编译器创建的 .pdb 文件。 使用 IDE 在 Visual Studio 中创建项目时,/Fd 选项设置为创建名为 <project.pdb>.pdb 文件。

    如果使用生成文件生成 C/C++应用程序,并且指定 /ZI/Zi 而不使用 /Fd 指定文件名,编译器将创建两个 .pdb 文件:

    • VC<x.pdb>,其中 <x> 表示 Microsoft C++ 编译器的版本,例如 VC11.pdb

      VC<x.pdb> 文件存储单个对象文件的所有调试信息,并驻留在项目生成文件所在的同一目录中。 每次创建对象文件时,C/C++编译器都会将调试信息合并到 VC<x.pdb> 中。 因此,即使每个源文件都包含常见的头文件(如 <windows.h>),这些标头中的 typedefs 仅存储一次,而不是存储在每个对象文件中。 插入的信息包括类型信息,但不包括符号信息,例如函数定义。

    • <project>.pdb

      <project.pdb> 文件存储项目 .exe 文件的所有调试信息,并驻留在 \debug 子目录中。 <project.pdb> 文件包含完整的调试信息,包括函数原型,而不仅仅是 VC<x.pdb> 中找到的类型信息。

    VC<x.pdb><project.pdb> 文件都允许增量更新。 链接器还会在创建.exe.dll 文件中嵌入 .pdb 文件的路径。

  • DLL 导出表

    用于 dumpbin /exports 查看 DLL 导出表中可用的符号。 DLL 导出表中的符号信息有助于处理 Windows 消息、Windows 过程 (WindowProc)、COM 对象、封送或不具有其符号的任何 DLL。 符号可用于任何 32 位系统 DLL。 调用顺序列出,当前函数(最深层嵌套)位于顶部。

    通过读取 dumpbin /exports 输出,可以看到确切的函数名称,包括非字母数字字符。 查看确切的函数名称对于在函数上设置断点很有用,因为可以在调试器中的其他位置截断函数名称。 有关详细信息,请参阅 dumpbin /exports

Web 应用程序

将 ASP.NET 应用程序的web.config文件设置为调试模式。 调试模式会导致 ASP.NET 为动态生成的文件生成符号,并使调试器能够附加到 ASP.NET 应用程序。 如果从 Web 项目模板创建项目,Visual Studio 会在开始调试时自动设置此设置。

调试时加载符号

可以在调试时使用 模块调用堆栈局部变量自动或任何 监视 窗口加载符号或更改符号选项。 有关详细信息,请参阅熟悉调试器如何附加到应用

在“模块”窗口中使用符号

在调试期间,“ 模块” 窗口显示调试器正在视为用户代码或“我的代码”及其符号加载状态的代码模块。 还可以在 “模块” 窗口中监视符号加载状态、加载符号和更改符号选项。

在调试时监视或更改符号位置或选项:

  1. 若要在调试时打开 “模块 ”窗口,请选择 “调试>Windows>模块 ”(或按 Ctrl + Alt + U)。
  2. 在“ 模块 ”窗口中,右键单击 “符号状态 ”或“ 符号文件” 标头或任何模块。
  3. 在上下文菜单中,选择以下选项之一:
选项 DESCRIPTION
加载符号 对于具有跳过、未找到或未加载符号的模块显示。 尝试从选项>调试>页面上指定的位置加载符号。 如果未找到或未加载符号文件,请启动 文件资源管理器 ,以便可以指定要搜索的新位置。
符号加载信息 显示加载的符号文件的位置,或调试器找不到文件时搜索的位置。
符号设置 打开 “选项>调试>符号 ”页,可在其中编辑和添加符号位置。
始终自动加载 将所选符号文件添加到调试器自动加载的文件列表中。
将源反编译为符号文件 对于 .NET 代码,可以选择此选项,然后按照 生成和嵌入程序集源中的说明进行作。

使用“未加载符号/未加载源”页面

调试器可通过多种方式中断没有可用符号或源文件的代码:

  • 单步执行代码。
  • 通过断点或异常中断代码。
  • 切换到其他线程。
  • 通过在 “调用堆栈 ”窗口中双击帧来更改堆栈帧。

发生这种情况时,调试器将显示 “未加载符号 ”或 “无源加载 ”页,以帮助查找和加载必要的符号或源。

未加载符号页

若要使用“未加载符号文档”页以协助查找和加载缺失的符号:

  • 若要更改搜索路径,请选择未选择的路径,或选择 “新建路径 ”或“ 新建 VSTS 路径 ”,然后输入或选择新路径。 选择 “加载 ”以再次搜索路径,并在找到符号文件时加载符号文件。
  • 为了覆盖任何符号选项并重试搜索路径,请选择 “浏览”并找到 <可执行文件名称>。 找到符号文件时会加载,如果找不到,文件资源管理器将打开以便您手动选择符号文件。
  • 若要打开符号设置页以配置行为,请选择 “更改符号设置 ”(或选择 “选项>调试>符号”)。
  • (高级)若要一次在新窗口中显示反汇编,请选择 视图反汇编,或选择“ 选项”对话框 ,以设置选项,以在找不到源或符号文件时始终显示反汇编。 有关详细信息,请参阅 “查看反汇编代码”。
  • 若要显示搜索的位置和结果,请展开 符号加载信息
  • 对于 C# 代码,还可以选择从“未加载符号”或“无源加载”页中反编译源代码

如果在执行其中一个选项后调试器找到 .pdb 文件,并且可以使用 .pdb 文件中的信息检索源文件,则会显示源。 否则,它会显示 无源加载 页,描述问题,并包含可能解决该问题的操作链接。

若要向解决方案添加源文件搜索路径,请执行以下作:

可以指定调试器搜索源文件的位置,并从搜索中排除特定文件。

  1. 解决方案资源管理器中选择解决方案,然后选择 “属性” 图标,按 Alt+Enter,或右键单击并选择“ 属性”。

  2. 选择 “调试源文件”。

    “调试源文件”页

  3. 包含源代码的目录下,键入或选择要搜索的源代码位置。 使用 “新建线条 ”图标可以添加更多位置、 向上向下 箭头图标来重新排序它们,或者 使用 X 图标将其删除。

    注释

    调试器仅搜索指定的目录。 必须为要搜索的任何子目录添加条目。

  4. “不查找这些源文件”下,键入要从搜索中排除的源文件的名称。

  5. 选择 “确定”“应用”。