在 Visual Studio 上下文中,当调试应用时,这通常意味着你在附加了调试器的情况下(即在调试器模式下)运行应用程序。 执行此操作时,调试器在运行过程中可提供许多方法让你查看代码的情况。 你可以逐步执行代码、查看变量中存储的值、设置对变量的监视以查看值何时改变、检查代码的执行路径等。
01 设置断点(F9)并启动调试器(F5)
断点是可靠调试的最基本和最重要的功能。断点指示 Visual Studio 应在哪个位置挂起你的运行代码,以使你可以查看变量的值或内存的行为,或确定代码的分支是否运行。要进行调试,需要在调试器附加到应用进程的情况下启动应用。 F5(“调试”>“开始调试”)是执行该操作最常见的方法。因此我们首先设置断点再开始调试。
按 F5(“调试”>“开始调试”)或调试工具栏中的“开始调试”按钮
,调试器将运行至它遇到的第一个断点。 如果应用尚未运行,则按 F5 会启动调试器并在第一个断点处停止。
02 单步调试(F11)
要在附加了调试器的情况下启动应用,请按 F11(“调试”>“单步执行”)。 F11 是单步执行”命令,每按一次,应用就执行下一个语句。 使用 F11 启动应用时,调试器会在执行的第一个语句上中断。
黄色箭头表示调试器暂停处的语句,它还在同一点上暂停应用执行(此语句尚未执行)。
F11 是一种以最详尽方式检查执行流的好方法。 (为了更快地浏览代码,VS展示了一些其他选项。)默认情况下,调试器会跳过非用户代码(如果需要更多详细信息,请参阅仅我的代码)。
在托管代码中将看到一个对话框,询问你是否希望在自动跳过属性和运算符时收到通知(默认行为)。 若稍后想更改设置,请在“调试”下的“工具”>“选项”菜单中禁用“单步跳过属性和运算符”设置。
03 单步跳过代码以跳过函数(F10)
如果所在的代码行是函数或方法调用),则可以按 F10(“调试”>“单步跳过”)而不是 F11。
按 F10 将使调试器前进,但不会单步执行应用代码中的函数或方法(代码仍将执行)。
上图中当前程序走到32行,按下 F10 后,直接走到34行,而没有进入到调用的方法中。
04 单步执行属性
如前所述在默认情况下,调试器会跳过托管属性和字段,但通过“单步执行特定内容”命令可替代此行为。
右键单击属性或字段,选择“单步执行特定内容”,然后选择一个可用选项。
在此示例中,通过“单步执行特定函数”将转到 shape.Width 的 Set 属性代码处。
05 导航代码(使用鼠标快速运行到代码中的某个点)
在调试器中,将鼠标悬停在代码行上,直到“运行到单击处”(将执行运行到此处)按钮
出现在左侧。
自 Visual Studio 2017 起,可用使用“运行到单击位置”(将执行运行到此处)按钮。 低版本的VS,可以通过以下方式达到上述效果 (1)通过鼠标拖拽“黄色箭头”到目标位置行。 (2)参考第7步骤,“运行到光标处”功能。 单击“运行到单击处”(将执行运行到此处)按钮。 调试器将前进到单击的代码行。 使用此按钮类似于设置临时断点。 此命令对于快速到达应用代码的可见区域也很方便。 你可在任何打开的文件中使用“运行到单击处”。
06 使调试器从当前函数中跳出(Shift + F11)
有时你可能希望继续调试会话,但在整个当前函数中一直使调试器前进。
按 Shift+F11(或“调试”>“单步跳出”)。
此命令将恢复应用执行(并使调试器前进),直到当前函数返回。
07 运行到光标处(Ctrl + F10)
右键单击应用中的代码行,然后选择“运行到光标处”。 此命令将启动调试并在当前代码行上设置临时断点。
如果设置了断点,则调试器会在其命中的第一个断点处暂停。
按 F5,直至到达在其上选择了“运行到光标处”的代码行。
当编辑代码并希望快速设置临时断点并同时启动调试器时,此命令很有用。
调试时可使用“调用堆栈”窗口中的“运行到光标处”。
08 快速重启应用
单击调试工具栏中的“重启”按钮
(Ctrl+Shift+F5)。
当你按下“重启”时,与停止应用并重启调试器相比,它节省了时间。 调试器在执行代码命中的第一个断点处暂停。
若确实要停止调试器并返回到代码编辑器,可以按红色停止
按钮而不是“重启”。
shapes 集合中有3笔记录。循环中运行到第2次时,控制台已经在第1次循环结束时输出打印了内容。
此时单击调试工具栏中的“重启”按钮
(Ctrl+Shift+F5),控制台窗口关闭,立即重新开启一个新的控制台窗口。此过程的速度比停止调试,然后再按下F5调试的速度更快。
09 使用数据提示检查变量
在调试器中暂停时,将鼠标悬停在对象上并看到其默认属性值。通常,当尝试调试问题时,通过此方式可以试图找出变量是否存储了期望它们在特定应用状态具有的值。
展开对象以查看其所有属性(例如本示例中的 sharp 对象)。
通常,在调试时,你需要快速检查对象的属性值,数据提示是一种实现此目的的好方法。
在大多数受支持的语言中,可在调试会话中途编辑代码。 有关详细信息,请参阅编辑并继续。
10 使用“自动”和“局部变量”窗口检查变量
调试时,查看代码编辑器底部的“自动”窗口。
在“自动”窗口中,可看到变量及其当前值和类型。 “自动”窗口显示当前行或前一行使用的所有变量(在 C++ 中,该窗口显示前三个代码行中的变量。 查看文档以了解特定于语言的行为)。
接下来,查看“局部变量”窗口。 “局部变量”窗口显示当前范围中的变量。
有关详细信息,请参阅在“自动”窗口和“局部变量”窗口中检查变量。
在 JavaScript 中,支持“局部变量”窗口,但不支持“自动”窗口。
11 设置监视
可使用“监视”窗口指定要关注的变量(或表达式)。
在调试时,右键单击对象并选择“添加监视”。
在本示例中,在 sharp 对象上设置了监视,当在调试器中移动时,可看到其值发生了变化。 与其他变量窗口不同,“监视”窗口始终显示正在监视的变量(当超出范围时,它们会变灰)。
有关详细信息,请参阅使用“监视”窗口和“快速监视”窗口设置监视
12 检查调用堆栈
调试时单击“调用堆栈”窗口,默认情况下,该窗口在右下方窗格中打开。
“调用堆栈”窗口显示方法和函数被调用的顺序。 最上面一行显示当前函数(此示例中的 Draw
方法)。 第二行显示 Draw 是从Main 函数调用的,依此类推。 调用堆栈是检查和理解应用执行流的好方法。
可双击代码行来查看该源代码,这也会更改调试器正在检查的当前范围。 此操作不会使调试器前进。
还可使用“调用堆栈”窗口中的右键单击菜单执行其他操作。 例如,你可将断点插入到指定的函数中,使用“运行到光标处”重启应用,然后检查源代码。 请参阅如何:检查调用堆栈。
13 检查异常
应用引发异常时,调试器会将你转至引发异常的代码行。
异常帮助程序是帮助调试错误的好功能。 你还可以执行其他操作,如查看错误详细信息及从异常帮助程序添加监视。 或者,如有需要可更改引发特定异常的条件。 有关如何在代码中处理异常的详细信息,请参阅调试技术和工具。
查看详细信息
展开“异常设置”节点以查看有关如何处理此异常类型的更多选项。异常设置 -> 编辑条件
14 编辑代码并继续调试
如果在调试会话期间发现一个要在代码中测试的更改,则也可以执行此操作。
c2.First.Value
的第二个实例且将 c2.First.Value
更改为 c2.Last.Value
。
F10 一次使调试器前进一个语句,但是是跳过函数而不是单步执行它们(跳过的代码仍然执行)。
15 移动指针以更改执行流
调试器暂停时,对源代码的边距中的黄色箭头或反汇编窗口标记要执行的下一个语句的位置。 你可以通过移动此箭头执行的下一个语句。 可以跳过了一部分代码,或返回到上一代码行。 移动指针可用于如跳过包含已知的 bug 的代码部分的情况。
若要更改要执行的下一个语句,调试器必须处于中断模式。 在源代码中或反汇编窗口中,将黄色箭头拖到不同的行,或右键单击你想要执行的下和选择的行设置下一语句。
程序计数器直接跳转到新位置,并说明旧的和新执行点之间不会执行。 但是,如果向后移动执行点,则不撤消插入的指令。
1、将下一条语句移动到另一个函数或范围通常会导致调用堆栈损坏,导致一个运行时错误或异常。 如果尝试将下一条语句移动到另一个范围,则调试器将打开一个含有警告的对话框,并提供一个取消该操作的机会。
2、当启用“编辑并继续”时,如果你进行了“编辑并继续”无法立即重新映射的编辑,那么 “设置下一语句” 将失败。 例如,如果你编辑了 catch 块中的代码,将发生这种情况。 在此情况下,会显示错误消息,告知你不支持该操作。 在托管代码中,您不能移动下一个语句,如果: (1)下一条语句与当前语句不在同一个方法中。 (2)在实时调试启动调试。 (3)正在进行的调用堆栈展开。 (4)已引发一个 System.StackOverflowException 或 System.Threading.ThreadAbortException 异常