在前面的课程中,你学习了如何使用调试器来查看程序的执行路径。然而,单步执行只是使调试器有用的方面之一。调试器还可以让你在单步执行代码时检查变量的值,而无需修改代码。
按照前面课程的惯例,我们的示例将使用 Visual Studio — 如果你使用的是其他 IDE/调试器,命令的名称可能略有不同,或者位于不同的位置。
警告
如果你是回来查看本课程的,请确保你的项目是使用调试构建配置编译的(更多信息请参阅 0.9 — 配置你的编译器:构建配置)。如果你使用的是发布配置来编译项目,调试器的功能可能无法正常工作。
监视变量
监视变量是在调试模式下程序执行时检查变量值的过程。大多数调试器提供了几种方法来实现这一点。
让我们来看一个示例程序:
#include <iostream>
int main()
{
int x{ 1 };
std::cout << x << ' ';
x = x + 2;
std::cout << x << ' ';
x = x + 3;
std::cout << x << ' ';
return 0;
}
这是一个非常直接的示例程序 —— 它打印数字 1、3 和 6。
首先,将光标运行到第 6 行。
此时,变量x
已经被创建并初始化为值 1,因此当我们检查x
的值时,我们应该期望看到值 1。
检查像x
这样的简单变量的值最简单的方法是将鼠标悬停在变量x
上。一些现代调试器支持这种检查简单变量的方法,这是最直接的方式。
对于 Code::Blocks 用户
如果你使用的是 Code::Blocks,这个选项(莫名其妙地)默认是关闭的。让我们将其打开。首先,转到"Settings"菜单 > “Debugger…"。然后在 GDB/CDB 调试器节点下,选择"Default"配置文件。最后,勾选标记为"Evaluate expression under cursor"的复选框。
将鼠标光标悬停在第 6 行的变量x
上,你应该会看到类似以下内容:
请注意,你可以将鼠标悬停在任何变量x
上,而不仅仅是当前行上的那个。例如,如果我们把鼠标悬停在第 12 行的x
上,我们会看到相同的值:
如果你使用的是 Visual Studio,你还可以使用"QuickWatch”。用鼠标高亮显示变量名x
,然后从右键菜单中选择"QuickWatch"。
这将弹出一个子窗口,显示变量的当前值:
如果你打开了"QuickWatch",现在可以将其关闭了。
现在,让我们在单步执行程序时观察这个变量的变化。选择两次"跳过函数",或者将光标运行到第 9 行。变量x
现在应该有值 3。检查它并确保确实如此!
监视窗口
使用鼠标悬停或"QuickWatch"方法检查变量在你想知道某个特定时刻变量的值时是可以的,但这种方法并不适合在运行代码时观察变量值的变化,因为你需要不断地重新悬停/重新选择变量。
为了解决这个问题,所有现代集成调试器都提供了另一个功能,称为监视窗口。监视窗口是一个窗口,你可以在其中添加你想要持续检查的变量,这些变量将在你单步执行程序时更新。当你进入调试模式时,监视窗口可能已经在你的屏幕上,如果没有,你可以通过 IDE 的窗口命令将其打开(这些命令通常位于"View"或"Debug"菜单中)。
对于 Visual Studio 用户
在 Visual Studio 中,监视窗口可以在"Debug"菜单 > “Windows” > “Watch” > “Watch 1"中找到。请注意,你必须处于调试模式才能启用此选项,因此请先进入你的程序。
这个窗口出现的位置(停靠在左侧、右侧或底部)可能会有所不同。你可以通过拖动"Watch 1"标签到应用程序窗口的不同位置来更改其停靠位置。
对于 Code::Blocks 用户
在 Code::Blocks 中,监视窗口可以在"Debug"菜单 > “Debugging windows” > “Watches"中找到。这个窗口可能会作为一个独立窗口出现。你可以通过将其拖动到主窗口上来将其停靠。
对于 VS Code 用户
在 VS Code 中,监视窗口在调试模式下会出现在左侧,位于调用堆栈上方。
你现在应该会看到类似以下内容:
监视窗口可能已经包含了一些内容,也可能没有。
通常有两种不同的方法可以将变量添加到监视窗口:
- 拉起监视窗口,并在监视窗口的最左侧列中输入你想要监视的变量的名称。
- 在代码窗口中,右键单击你想要监视的变量,然后选择"Add Watch”(Visual Studio)或"Watch x”(将
x
替换为变量的名称)(Code::Blocks)。
如果你尚未处于调试会话中,并且程序的执行标记不在第 9 行,请启动一个新的调试会话,并将光标运行到第 9 行。
现在,将变量"x"添加到你的监视列表中。你现在应该会看到这个:
现在选择两次"跳过函数",或者将光标运行到第 12 行,你应该会看到x
的值从 3 变为 6。
超出作用域的变量(例如,在已经返回到调用者的函数中的局部变量)将保留在你的监视窗口中,但通常会被标记为"不可用",或者可能会显示最后已知值,但会变灰。如果变量重新进入作用域(例如,函数再次被调用),它的值将再次开始显示。因此,即使变量超出作用域,也可以将其保留在监视窗口中。
使用监视窗口是观察变量值随时间变化的最佳方式,当你单步执行程序时。
为监视变量设置断点
一些调试器允许你为监视变量而不是某一行设置断点。这将导致程序在该变量的值发生变化时停止执行。
例如,在上面的程序中为变量x
设置这样的断点将导致调试器在执行第 8 行和第 11 行后停止(这是x
的值被改变的地方)。
对于 Visual Studio 用户
在 Visual Studio 中,确保你的变量正在被监视。接下来,进入你的程序并转到监视窗口。右键单击变量并选择"Break when value changes"。
每次开始调试会话时,你需要重新启用"Break when value changes"。
监视窗口也可以计算表达式
监视窗口还可以让你计算简单表达式。如果你还没有,将光标运行到第 12 行。然后尝试在监视窗口中输入x + 2
并看看会发生什么(它应该计算为 8)。
你还可以在代码中高亮显示一个表达式,然后通过悬停或通过右键上下文菜单将其添加到监视窗口来检查该表达式的值。
警告
监视表达式中的标识符将计算为其当前值。如果你想了解代码中某个表达式实际计算的结果,请先将光标运行到该位置,以便所有标识符都有正确的值。
局部监视
由于在调试时检查函数内局部变量的值是很常见的,许多调试器会提供某种方法来快速监视所有在作用域内的局部变量的值。
对于 Visual Studio 用户
在 Visual Studio 中,你可以在"Locals"窗口中查看所有局部变量的值,该窗口可以在"Debug"菜单 > “Windows” > “Locals"中找到。请注意,你需要处于调试会话中才能激活这个窗口。
对于 Code::Blocks 用户
在 Code::Blocks 中,这被集成到监视窗口中,位于"Locals"节点下。如果你看不到任何内容,可能是因为没有局部变量,或者你需要展开该节点。
对于 VS Code 用户
在 VS Code 中,局部变量的值可以在调试模式下停靠在左侧的"VARIABLES"部分中找到。你可能需要展开"Locals"节点。
如果你只是想监视局部变量的值,请先检查局部窗口,它应该已经在那了。