了解 Visual Studio 中调试程序在工作效率方面的提示和技巧

通过阅读本主题,了解 Visual Studio 调试器在工作效率方面的一些提示和技巧。 若要了解调试器的基本功能,请参阅初探调试器。 在本主题中,我们将了解功能介绍中没有涉及的一些领域。

键盘快捷方式

有关与调试相关的最常用键盘快捷方式的列表,请参阅键盘快捷方式中的调试部分。

固定数据提示

如果你在调试时,经常将鼠标悬停在数据提示上,就可能想固定变量的数据提示,方便自己随时查看。 即使在重新启动后,固定的变量也能保持不动。 要固定数据提示,请在鼠标悬停其上时单击固定图标。 你可以固定多个变量。

固定数据提示

还可以通过其他几种方式自定义数据提示,例如保持数据提示展开(粘性数据提示),或使数据提示透明。 有关详细信息,请参阅在代码编辑器中查看数据提示中的数据值

编辑代码并继续调试(C#、VB、C++)

在 Visual Studio 支持的大多数语言中,你都可以在调试会话的过程中编辑代码,然后继续调试。 要使用此功能,请先在调试器中暂停,用鼠标点击进入代码,进行编辑,然后按 F5F10F11 键继续调试。

编辑并继续调试

有关功能使用和功能限制的详细信息,请参阅编辑并继续

编辑 XAML 代码并继续调试

若要在调试会话期间修改 XAML 代码,请参阅使用 XAML 热重载编写和调试正在运行的 XAML 代码

调试难以重现的问题

如果在应用中重新实现特定状态很困难或很费时,可以考虑使用条件断点。 你可以使用条件断点并对其加以筛选,以免破坏应用代码,直到应用进入所需的状态(例如,变量正在存储错误数据的状态)。 你可以使用表达式、筛选器、命中次数等来设置条件。

创建条件断点

  1. 右键单击断点图标(红色球),然后选择“条件”。

  2. 断点设置窗口中,键入一个表达式。

    条件断点

  3. 如果你对另一种类型的条件感兴趣,请在断点设置对话框中选择筛选器,而不是条件表达式,然后按照筛选器的提示操作。

配置要在调试器中显示的数据

对于 C#、Visual Basic 和 C++(仅限 C++/CLI 代码),可以使用 DebuggerDisplay 属性指示调试器显示哪些信息。 对于 C++ 代码,可以使用 Natvis 可视化效果执行相同的操作。

重复附加到同一应用程序

使用附加到进程功能,选择“调试”>“重新附加到进程”(Shift+Alt+P),可以快速重新附加到先前附加到的进程。 当选择此命令时,调试程序会立即尝试附加到最后连接的进程,方法是首次尝试匹配先前的进程 ID,如果失败,将匹配先前的进程名称。 如果不找到任何匹配项,或多个进程具有相同的名称,“附加到进程” 对话框将打开,这样您就可以选择正确的进程。

跟踪超出范围的对象(C#、Visual Basic)

使用“监视”窗口等调试器窗口可以轻松查看变量。 但是,当“监视”窗口中的某个变量超出范围时,你可能会注意到它显示为灰色。在某些应用方案中,即使变量超出范围,变量的值也可能发生变化,你可能需要仔细观察它(例如,可能会对变量进行垃圾回收)。 可以通过在“监视”窗口中为变量创建对象 ID 来跟踪该变量。

创建对象 ID

  1. 在要跟踪的变量附近设置一个断点。

  2. 启动调试器 (F5) 并在断点处停止。

  3. 在“局部变量”窗口(“调试”>“窗口”>“局部变量”)中找到该变量,右键单击该变量,然后选择“创建对象 ID”。

    创建对象 ID

  4. 应该会在“局部变量” $ 窗口中看到 $ 窗口中设置断点来中断调用函数返回到的指令或行处的执行。 此变量是对象 ID。

  5. 右键单击对象 ID 变量并选择“添加监视”。

有关详细信息,请参阅创建对象 ID

查看函数的返回值

若要查看函数的返回值,请在逐句通过代码时查看“自动”窗口中显示的函数。 若要查看函数的返回值,请确保你感兴趣的函数已经执行(如果当前已在函数调用中停止,请按一次 F10)。 如果窗口关闭,请使用“调试”>“窗口”>“自动”打开“自动”窗口。

“自动”窗口

此外,也可以在“即时”窗口中输入函数来查看返回值。 (使用“调试”>“窗口”>“即时”打开它。)

“即时”窗口

此外,还可以在监视即时窗口中使用伪变量,如 $ReturnValue

在可视化工具中检查字符串

在使用字符串时,如果能看到完整的、带格式的字符串会很有帮助。 要查看纯文本、XML、HTML 或 JSON 字符串,请将鼠标悬停在包含字符串值的变量上,然后单击放大镜图标 VisualizerIcon

打开字符串可视化工具

字符串可视化工具可以帮你确定字符串的格式是否正确,具体取决于字符串的类型。 例如,如果字段为空,表明可视化工具类型未识别出该字符串。 有关详细信息,请参阅“字符串可视化工具”对话框

JSON 字符串可视化工具

对于调试器窗口中显示的其他几个类型(例如 DataSet 和 DataTable 对象),同样可以打开内置可视化工具。

分析内存使用情况

可以使用内存使用工具拍摄和比较堆的快照、优化内存使用情况以及查找内存泄漏。 有关详细信息,请参阅选择内存分析工具

创建转储文件

转储文件是一个快照,其显示某个时间点正在为应用执行的进程和已为应用加载的模块。 带堆信息的转储还包括该时间点的应用内存的快照。 转储最常用于调试开发人员无权访问的计算机中的问题。

如果需要保存转储文件,请选择“调试”>“将转储另存为”。

若要分析转储文件,请在 Visual Studio 中选择“文件”>“打开”。 若要开始使用转储文件进行调试,请选择“仅调试托管内存”、“仅调试本机内存”、“调试混合型内存”或“调试托管内存”。

有关详细信息,请参阅转储文件

在已处理的异常处中断代码

调试器会在发生未经处理的异常时中断代码。 不过,已处理的异常(例如,发生在 try/catch 块中的异常)也可能是 bug 的来源,你可能希望调查它们的发生时间。 可以通过配置“异常设置”对话框中的选项,将调试器配置为在发生已处理的异常时也中断代码。 通过选择“调试”>“窗口”>“异常设置”打开此对话框。

通过异常设置对话框,你可以让调试器在特定异常处中断代码。 在下图中,调试器会在发生 System.NullReferenceException 时中断代码。 有关详细信息,请参阅管理异常

“异常设置”对话框

更改执行流

让调试器暂停在某行代码上,用鼠标抓住左侧的黄色箭头指针。 将黄色箭头指针移动到代码执行路径中的其他点上。 然后通过 F5 键或步骤命令继续运行应用。

移动执行指针

通过更改执行流,你可以进行测试不同代码执行路径或重新运行代码等操作,而无需重启调试器。 有关详细信息,请参阅移动执行指针

警告

通常你需要小心使用此功能,工具提示中会出现警告。 你也可能会看到其他警告。 移动指针无法将应用还原到更早的应用程序状态。

调试死锁和争用条件

如果需要调试的问题对于多线程应用程序很常见,在调试时查看线程的位置,通常会有所帮助。 可使用源中显示线程按钮轻松完成此操作。

在源代码中显示线程:

  1. 调试时,单击“调试”工具栏中的“在源中显示线程”按钮 在源中显示线程

  2. 查看窗口左侧的滚动条槽。 在这一行,你可以看到“线程标记”图标 线程标记,类似于两根细线。 线程标记指示线程在此位置停止。

    注意,线程标记可能被断点不完全遮挡。

  3. 将指针悬停在线程标记上。 屏幕上将显示数据提示。 数据提示将告诉你每个已停止线程的名称和线程 ID。

    你还可以在“并行堆栈”窗口中查看线程的位置。

进一步了解调试器如何附加到应用(C#、C++、Visual Basic、F#)

若要附加到正在运行的应用,调试器将加载为想要调试的应用的相同内部版本生成的符号 (.pdb) 文件。 在某些情况下,了解符号文件的一些知识非常有用。 你可在模块窗口中检查 Visual Studio 如何加载符号文件。

调试时,通过选择“调试”>“窗口”>“模块”来打开“模块”窗口。 “模块”窗口可以告诉你调试器将哪些模块视为用户代码或我的代码,以及模块的符号加载状态。 在大多数情况下,调试器会自动查找用户代码的符号文件,但是如果你想要单步执行(或调试).NET 代码、系统代码或第三方库代码,则需要执行额外的步骤来获取正确的符号文件。

在“模块”窗口中查看符号信息

你可以直接在模块窗口中右键单击并选择加载符号来加载符号信息。

有时,应用开发人员发布的应用不包含匹配的符号文件 (为了减少占用的空间),但会为内部版本保留一份匹配的符号文件,用于以后调试发布版本。

了解如何调试器如何区分用户代码,请参阅仅我的代码。 若要了解有关符号文件的详细信息,请参阅在 Visual Studio 调试器中指定符号 (.pdb) 文件和源文件

了解详细信息

有关其他提示和技巧以及更多详细信息,请参阅以下博客文章:

键盘快捷方式