章节目录

调用堆栈

本节阅读量:

现代调试器还包含一个非常有用的调试信息窗口,即调用堆栈窗口。

当程序调用函数时,您已经知道它为当前位置添加标记,进行函数调用,然后返回。它如何知道返回到哪里?答案是它在调用堆栈中保持记录。

调用堆栈是为到达当前执行点而调用的所有途径的函数的列表。调用堆栈包括被调用的每个函数的信息,以及函数返回时将返回到哪一行的标记。每当调用新函数时,该函数都会添加到调用堆栈的顶部。当前函数返回给调用者时,它将从调用堆栈的顶部删除,并且将返回到它下面的函数。

调用堆栈窗口是显示当前调用堆栈的调试器窗口。如果看不到调用堆栈窗口,则需要设置IDE显示它。

让我们使用示例程序来查看调用堆栈:

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

void a()
{
	std::cout << "a() called\n";
}

void b()
{
	std::cout << "b() called\n";
	a();
}

int main()
{
	a();
	b();

	return 0;
}

在此程序的第5行和第10行上放置断点,然后启动调试模式。因为首先调用函数a,所以将首先命中第5行上的断点。

此时,您应该看到这样的内容:

调用堆栈

您的IDE可能会表现出一些差异:

  1. 函数名和行号的格式可能不同
  2. 您的行号可能略有不同(相差1)
  3. 您可能会看到许多其他疯狂命名的函数,而不是[外部代码]。

这些差异无关紧要。

这里相关的是前两行。从下往上,我们可以看到函数main首先被调用,然后函数a被调用。

函数a旁边的第5行显示了当前执行点的位置(与代码窗口中的执行标记匹配)。第二行上的第17行表示当控制返回到函数main时将返回的行。

现在,点击继续,推进到下一个断点,该断点将在第10行。调用堆栈应更新以反映新情况:

调用堆栈

您会注意到,函数b现在是调用堆栈的顶行,反映了函数b是正在执行的函数这一事实。请注意,函数a不再在调用堆栈上表示。这是因为函数a在返回时已从调用堆栈中删除。

现在,点击继续,我们将再次命中第5行上的断点(因为函数b调用函数a)。调用堆栈如下所示:

调用堆栈

现在在调用堆栈上有三个函数:(从下到上)main,它调用函数b,b调用了函数a。

当您的断点被命中,并且您想知道调用了哪些函数来到达代码中的该特定点时,调用堆栈与断点一起使用非常有用。


结论

祝贺您,您现在已经了解了使用集成调试器的基础知识!使用单步执行、断点、监视和调用堆栈窗口,您现在有了能够调试几乎任何问题的基础。像许多事情一样,要想熟练地使用调试器,需要进行一些练习和尝试。但是,我们再次重申,用于学习如何有效使用集成调试器的时间将比调试程序节省的时间多得多!


3.7 监视变量

上一节

3.9 在问题变成问题前进行避免

下一节