章节目录

断点

本节阅读量:

虽然单步执行对于孤立地检查代码的每一行很有用,但在大型程序中,单步执行代码甚至可能需要很长时间才能到达您想要更详细地检查的点。

幸运的是,现代调试器提供了更多的工具来帮助我们有效地调试程序。在本课中,我们将研究一些调试器功能,这些功能使我们能够更快地定位到代码。


运行到光标

第一个有用的命令通常称为Run-to-cursor。Run-to-cursor命令执行程序,直到执行到达鼠标选择的语句。然后它将控制权返回给您,以便您可以从该点开始调试。这为在代码中的特定点开始调试提供了一种有效的方法,或者,如果已经在调试,则可以直接移动到要进一步检查的位置。

让我们使用一直在使用的相同程序来举例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <iostream>

void printValue(int value)
{
    std::cout << value << '\n';
}

int main()
{
    printValue(5);

    return 0;
}

只需右键单击第5行的任意位置,然后选择“Run to cursor”。

执行到所选位置

您将注意到程序开始运行,执行并移动到您刚才选择的行。然后现在正在等待进一步的调试命令。从这里,您可以单步执行您的程序,将程序运行到不同的位置,等等…

若您选择鼠标运行到一个无法执行的位置,那么将简单地运行您的程序,直到终止。


Continue

一旦您处于调试状态,您可能希望从该点开始运行程序。最简单的方法是使用continue命令。continue命令会让程序按照正常方式继续运行,要么直到程序终止,要么直到有东西触发中断,并将控制权再次返回给您(例如断点(breakpoint),我们将在本课后面介绍)。

让我们测试一下continue命令。如果您的执行标记不在第5行上,请运行光标到第5行。然后从该点选择“继续”。您的程序将完成执行,然后终止。


Start

continue命令有一个名为start的孪生兄弟。start命令执行与continue相同的操作,只是从程序的开头开始。它只能在尚未处于调试状态时调用。

如果在上面的示例程序上使用start命令,它将开始运行。虽然这看起来不起眼,但这只是因为我们没有告诉调试器中断程序。


断点

我们将在本节中讨论的最后一个主题是断点。断点是一个特殊的标记,它告诉调试器在调试模式下运行时,在断点处停止程序的执行。

设置断点时,您将看到出现一种新类型的图标。Visual Studio使用红色圆圈。

设置断点

在第5行上设置一个断点,如上图所示。

现在,选择Start命令让调试器运行代码,让我们看看断点的作用。您将注意到,调试器不是一直运行到程序的末尾,而是在断点处停止(执行标记位于断点图标的顶部):

运行到断点

这就好像您将运行光标到这一点。

与运行到光标相比,断点有几个优点。首先,断点将导致调试器在每次遇到它们时都将控制权返回给您(与运行到光标不同,每次调用运行到光标时,它只运行一次)。其次,设置的断点,它将一直存在,直到您删除它为止,而使用run-to-cursor,您必须在每次调用命令时定位要运行到的位置。

请注意,放置在不在执行路径中的行上的断点不会导致调试器暂停代码的执行。

让我们来看一个稍微修改的程序,它更好地说明了断点和运行到光标之间的区别:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <iostream>

void printValue(int value)
{
    std::cout << value << '\n';
}

int main()
{
    printValue(5);
    printValue(6);
    printValue(7);

    return 0;
}

首先,启动一个新的调试会话,然后运行光标到第5行。现在选择“继续”。程序将继续到末尾(它不会再次在第5行停止,即使第5行还会再执行两次)。

接下来,在第5行上放置一个断点,然后选择start。程序将在第5行停止。现在选择“继续”。程序将在第5行再次停止。再次选择“继续”,它将第三次停止。再继续一次,程序将终止。可以看到,断点导致程序停止的次数与该行的执行次数相同。


结论

现在,您了解了使用集成调试器来监视和控制程序执行方式的主要方法。虽然这些命令对于诊断代码流程问题(例如,确定是否调用某些函数)很有用,但它们只是集成调试器带来的好处的一部分。在下一课中,我们将开始探索检查程序状态的其他方法。


3.5 使用集成调试器:单步执行

上一节

3.7 监视变量

下一节