教程:使用 Visual Studio 调试C++代码
本文介绍分步演练中 Visual Studio 调试器的功能。 调试应用程序时,通常会使用附加的调试器运行应用。 调试器提供了许多方法来检查程序执行过程中的代码正在执行的操作。 可以单步执行代码并查看变量中存储的值,并设置对变量的监视,以查看值何时发生更改。 调试器可帮助你检查代码的执行路径,并确认代码分支正在运行。
在本教程中,你将:
- 启动调试器并在断点处暂停
- 了解在调试器中逐步执行代码的命令
- 检查数据提示和调试器窗口中的变量
- 检查调用堆栈
如果你不熟悉调试,建议在开始本教程之前阅读 对绝对初学者的调试。 如果想要更高级别的调试器功能视图,请参阅 首先查看调试器。
先决条件
安装了“使用 C++ 的桌面开发”工作负载的 Visual Studio 2022 版本 17.12 或更高版本。
- 若要免费安装 Visual Studio 2022,请转到 Visual Studio 下载 页。
- 若要免费安装 Visual Studio,请转到 发布和生成历史记录 页了解详细信息。
如果已有 Visual Studio,则可以从交互式开发环境(IDE)中安装工作负荷:
选择“工具”>“获取工具和功能”。
在 Visual Studio 安装程序中,选择 工作负载 选项卡。
选择“使用 C++ 的桌面开发”工作负载,然后选择“修改”。
按照提示操作并完成安装。
本教程使用C++演示应用程序和显示C++语法的屏幕截图。 大多数演示的功能也适用于 Visual Studio 支持的 C#、Visual Basic、F#、Python、JavaScript 和其他语言。 请记住一些限制:
F#:不支持“编辑并继续”功能。
F# 和 JavaScript:不支持“自动变量”窗口。
创建项目
按照以下步骤在 Visual Studio 中创建C++控制台应用程序项目。 项目类型提供快速启动所需的所有模板文件:
在 Visual Studio “开始”窗口中(文件>开始窗口),选择 创建新项目:
将 语言 筛选器设置为 C++,并将 平台 筛选器设置为 Windows。
在“搜索”框中,输入控制台,然后在结果列表中选择控制台应用 模板。
备注
如果未看到 控制台应用 模板,可以从 创建新项目 窗口安装它。 找到搜索结果后面的“未找到你要查找的内容?”部分,然后选择“安装更多工具和功能”。 在 Visual Studio 安装程序中,选择具有C++工作负载的 桌面开发并更新安装。 有关详细信息,请参阅 先决条件 部分。
选择 “下一步” 以继续到配置页。
输入 get-started-debugging 作为新应用的“项目名称”和“解决方案名称”。 选择默认“位置”或浏览到环境中的其他路径。
选择“创建”以创建新的 Node.js 项目。
Visual Studio 创建了您的新项目,并在 解决方案资源管理器中打开您的项目层次结构。 get-started-debugging.cpp 文件在代码编辑器中打开。
创建应用程序
通过在代码编辑器中编辑 get-started-debugging.cpp 文件,为项目创建新应用程序。
将模板提供的默认内容替换为以下代码:
#include <string>
#include <vector>
#include <iostream>
void SendMessage(const std::wstring& name, int msg)
{
std::wcout << L"Hello, " << name << L"! Count to " << msg << std::endl;
}
int main()
{
std::vector<wchar_t> letters = { L'f', L'r', L'e', L'd', L' ', L's', L'm', L'i', L't', L'h' };
std::wstring name = L"";
std::vector<int> a(10);
std::wstring key = L"";
for (int i = 0; i < letters.size(); i++)
{
name += letters[i];
a[i] = i + 1;
SendMessage(name, a[i]);
}
std::wcin >> key;
return 0;
}
启动调试器
现在,你已准备好开始调试更新的代码:
选择 F5 或“调试”>“启动调试”,启动调试会话。 还可以在“调试”工具栏中选择 “开始调试”
(实心绿色箭头图标)。
F5 键盘快捷方式使用附加到应用进程的调试器启动应用程序,但代码中尚没有任何特殊检查内容。 应用只需加载并看到控制台输出:
Hello, f! Count to 1 Hello, fr! Count to 2 Hello, fre! Count to 3 Hello, fred! Count to 4 Hello, fred ! Count to 5 Hello, fred s! Count to 6 Hello, fred sm! Count to 7 Hello, fred smi! Count to 8 Hello, fred smit! Count to 9 Hello, fred smith! Count to 10
本教程稍后将在调试器中更仔细地查看此应用,并浏览其他调试功能。
在调试工具栏中选择“停止”
(红色方块图标)来停止调试器。 还可以使用 Shift + F5 键盘快捷方式。
在正在运行的应用程序的控制台窗口中,选择任意键,然后选择 Enter 关闭窗口。
设置断点并启动调试器
尝试在调试器中的选定点设置断点并暂停:
返回到代码编辑器中的 get-started-debugging.cpp 文件,找到
main
函数的for
循环:for (int i = 0; i < letters.size(); i++) { name += letters[i]; a[i] = i + 1; SendMessage(name, a[i]); }
通过在包含代码语句
name += letters[i];
的行的左侧滚动条槽进行点击,在该行上设置断点。 Visual Studio 会在该区域中添加一个红色圆圈来表示设置的断点。
提示
还可以将光标放在代码行上,然后选择 F9 切换该行的断点。
断点是可靠调试的最基本和最重要功能之一。 断点指示你希望 Visual Studio 在哪个位置暂停运行中的代码。 暂停执行时,可以查看变量的值、检查内存的行为,或检查代码分支是否正在运行。
选择 F5 或“启动调试”,在调试器中启动应用。
Visual Studio 开始执行您的应用程序。 当调试器到达设置断点时,调试进程将暂停。
Visual Studio 向边栏中的红色断点圆添加黄色箭头,以表示调试器暂停所在的代码语句。 程序执行已暂停,指示的语句正在等待处理。
备注
F5 操作与应用程序当前的执行状态相关。 如果你的应用未运行,并且你选择 F5,调试器将启动你的应用并继续执行,直到它到达第一个设置断点。 此行为映射到“调试”>“启动调试”命令。 如果你的应用已在运行,并且你选择 F5,应用执行将继续,直到调试器到达下一个断点或程序结束。 此行为映射到“调试”>“继续” 命令。
当您知道要详细检查的代码行或部分代码时,断点是一项有用的功能。 有关可以设置的不同类型的断点的信息,例如条件断点,请参阅 使用正确的断点类型。
在调试程序中逐步执行代码
在调试器中浏览代码的一种便捷方法是使用 步骤命令。 这些命令允许你 进入、跳过和 跳出代码段,并在应用执行中 后退。
以下过程重点介绍了如何使用键盘快捷方式和步骤命令快速完成代码。 (等效的菜单操作显示在括号中。
在调试器中启动应用程序,方法是选择 F5 或 启动调试。
当调试器在
main
函数的for
循环中暂停时,按两次 F11(“调试”>“单步执行”)以跳转到SendMessage
方法调用。按两次 F11 后,执行将继续到代码语句
SendMessage(name, a[i]);
。再次选择 F11 以进入
SendMessage
方法。注意黄色指针会前进至
SendMessage
方法:F11 键盘快捷方式会启动“单步执行”命令,让应用一次执行一条语句。 这是一种详细检查执行流的好方法。 默认情况下,调试器跳过非用户代码。 有关详细信息,请参阅仅我的代码。 在本教程的后续部分,您将学习如何更有效地浏览代码。
检查
SendMessage
方法后,可以使用 Step Out 命令继续调试。 选择 Shift + F11(“调试”>“单步跳出”)。此命令将恢复应用执行(并推进调试器),直到当前方法或函数返回。
命令完成后,调试器会在
main
方法的for
循环中的SendMessage
方法调用处暂停。多次选择 、F11 和,直到再次返回到
SendMessage
方法调用。在方法调用中暂停调试器时,请选择 F10(“调试”>“逐过程执行”)。
请注意这一次,调试器这次没有进入
SendMessage
方法。 F10 快捷方式会推进调试器,而无需单步执行应用代码中的函数或方法(代码仍执行)。 如果在SendMessage
方法调用处选择 F10(而不是 F11),则会逐过程执行SendMessage
的实现代码。 此方法可用于跳过暂时不需要检查的代码。 有关在代码中进行移动的不同方法的详细信息,请参阅浏览调试器中的代码。
通过“运行到单击处”浏览代码
在调试器中执行代码的另一种方法是使用“运行到单击处”功能。 此操作类似于设置临时断点。
继续调试会话:
选择 F5 以继续执行到代码中的断点。
在代码编辑器中,滚动到
SendMessage
方法定义,并将鼠标悬停在std::wcout
函数上。将鼠标悬停在代码语句上,直到左侧出现“运行到单击处”
(绿色箭头图标)。 如果将鼠标悬停在图标上,则会看到工具提示“运行到此处”:
选择“运行到单击处”
。
调试器将执行推进到指示的位置。 在此示例中,调试器达到了对
std::wcout
函数的调用。
“运行到单击处”操作可以帮助你在应用代码的可见区域中快速跳转。 可以在代码编辑器中打开的任何文件中使用该功能。
快速重启应用
通过在调试工具栏中选择 “重启(圆形箭头图标)来快速重启应用。 还可以选择 “调试”> 重启 或使用 ctrl Ctrl + Shift + F5 键盘快捷方式。
重启 功能比停止应用并再次启动调试器更有效。
选择 重启时,调试器会在执行过程中遇到的第一个断点处暂停。 在此示例中,调试器会在在 for
循环中设置的断点处再次停止。
使用数据提示检查变量
有助于检查变量的功能是使用调试器的最有用优势之一。 通常,在调试问题时,你正尝试发现变量是否在特定时间存储预期值。 Visual Studio 提供了多种方法来帮助你完成此任务。
继续进行调试会话:
在
name += letters[i]
语句上暂停调试器时,将鼠标悬停在letters
变量上。 选择变量名称左侧的展开/折叠箭头,并在浮出控件菜单中查看其属性。数据提示 功能显示变量包含的所有元素。 请注意默认值,
size={10}
:接下来,将鼠标悬停在
name
变量上,并注意到其当前值(空字符串(""
)。多次选择 F5(“调试”>“继续”),以便多次循环访问
for
循环。 每次调试器暂停断点时,将鼠标悬停在name
变量上并检查当前值:变量的值随
for
循环的每个迭代而更改,其中显示了f
、fr
、fre
等值。
使用“自动”和“局部变量”窗口检查变量
另一种检查变量和值的方法是使用 自动窗口 和 局部变量窗口。 默认情况下,在调试应用时,这些窗口显示在 Visual Studio IDE 中的代码编辑器下方:
请注意代码编辑器下方的“Autos”窗口。
如果在调试会话期间看不到该窗口,请选择调试>Windows>Autos 来打开窗口。
“自动变量”窗口显示当前行或上一行上使用的所有变量及其当前值。 请记住,特定的编程语言可以演示变量和属性的唯一行为。 有关详细信息,请参阅 Visual Studio 语言指南。
接下来,查看“局部变量”窗口。 默认情况下,此窗口与 Autos 窗口对齐。
如果在调试会话期间未看到窗口,请选择 调试>Windows>局部变量,以打开窗口。
在 局部变量 窗口中,展开
letters
变量以显示其包含的元素。局部变量 窗口显示当前 作用域(即当前执行上下文)中的变量。
监视变量
如果你想监视特定变量的行为,可以设置一个监视:
在代码编辑器中,右键单击 name
变量并选择“添加监视”。 随即会在代码编辑器下方打开“监视”窗口。 可以使用 监视 窗口指定要跟踪的变量(或表达式)。
在调试器中的应用执行期间观看 name
变量时,可以看到其值更改。 与其他变量窗口不同,监视 窗口始终显示正在监视的变量。 当监视的变量不在范围内时,变量名称将灰显。
检查调用堆栈
Visual Studio 中的 调用堆栈 窗口显示调用方法和函数的顺序。 此窗口类似于 Eclipse 之类的某些 IDE 中的“调试”透视。 默认情况下,在代码编辑器下面的调试会话中,调用堆栈在右下窗格中可见。
当调试器在
for
循环中暂停时,请选择 调用堆栈 窗口以查看当前调用结构。如果在调试会话期间看不到该窗口,请选择“调试”>“窗口”>“调用堆栈”打开该窗口。
多次选择 F11(“调试”>“单步执行”),直至看到调试器在
SendMessage
方法处暂停。再次查看 调用堆栈 窗口:
在 调用堆栈 窗口中,上行显示当前函数(此应用中的
SendMessage
方法)。 第二行显示SendMessage
方法是从main
方法调用的,依此类推。
调用堆栈是检查和了解应用执行流的好方法:
双击代码行以浏览到源代码。 此操作还会更改调试器正在检查的当前范围,但它不会推进调试器。
访问 调用堆栈 窗口中编程元素的右键单击菜单。 例如,可将断点插入到指定的函数中、使用“运行到光标处”使调试器前进,以及转到源代码。 有关详细信息,请参阅 查看调用堆栈并使用调试器中的“调用堆栈”窗口。
更改执行流
Visual Studio 中调试器的另一个功能是能够更改应用的执行流:
按两次 F11(“调试”>“单步执行”)以运行
std::wcout
函数。调试器在
SendMessage
方法调用中暂停时,选择黄色箭头(执行指针)并将其拖动到变量左侧,并将箭头移动到上一个代码语句,std::wcout
。再次选择 F11。
调试器重新运行
std::wcout
函数。 可以在终端输出中跟踪进程。通过更改执行流,可以执行诸如测试不同代码执行路径或重新运行代码之类的操作,而无需重启调试器。
谨慎
使用此功能时请仔细注意。 选择黄色箭头时,Visual Studio 会在工具提示中显示警告,指示执行更改可能会产生意外后果。 可能还会看到其他警告,具体取决于你的方案。 请记住,移动指针无法将应用程序还原到以前的应用状态。
选择 F5 以完成应用执行。