栈帧查看与切换

📅 2026/7/7 10:54:16 👁️ 阅读次数 📝 编程学习
栈帧查看与切换

在使用GDB调试时,可以使用以下命令对调用栈进行查看

backtrace

或者简写为:

bt

bt命令用于查看当前线程的调用栈信息。

也可以指定只显示前几个栈帧:

bt 3

表示只显示最靠近当前执行位置的第3个栈帧。

如果想在查看调用栈时,同时显示每个栈帧中的局部变量,可以使用:

bt full

bt full比普通的bt输出更详细,适合排查程序崩溃时每一层函数中的变量值。


2、切换栈帧

使用如下命令可以对栈帧进行切换

frame n

或者简写为:

f n

其中n表示栈帧编号。

bt输出中,每个栈帧前面都会有编号,例如:

#0 add(int, int) at main.cpp:6 #1 calc(int) at main.cpp:13 #2 work(int) at main.cpp:19 #3 main() at main.cpp:25

其中:

栈帧编号含义
#0当前正在执行的函数,也就是最顶层栈帧
#1调用当前函数的上一层函数
#2再上一层调用者
#3更早的调用者

如果想切换到work函数对应的栈帧,可以执行:

f 2

切换栈帧后,GDB 的上下文也会切换到对应函数中。此时查看局部变量、函数参数、源码位置,都是针对当前选中的栈帧而言。


3、查看当前栈帧信息

查看当前栈帧的详细信息:

info frame

或者简写为:

i f

该命令可以查看当前栈帧的地址、调用关系、保存的寄存器信息等。

如果想查看某个栈帧的信息,常见做法是先切换到对应栈帧:

f 2 i f

也可以在支持的 GDB 版本中直接使用:

i f 2

小技巧:bt命令还能查看当前程序执行到哪里了,查看最顶层的栈帧,后面就是他当前执行所在行


4、查看当前栈帧的参数与局部变量

查看当前栈帧中的函数参数:

info args

查看当前栈帧中的局部变量:

info locals

例如,当前选中的是calc函数的栈帧,那么:

info args info locals

看到的就是calc函数中的参数和局部变量,而不是addmain中的变量。

这也是切换栈帧的重要作用:可以回到某一层函数调用现场,查看当时传入了什么参数、局部变量是什么值,从而分析程序为什么会执行到当前位置。

三、完整示例

下面通过一个包含 4 层函数调用的程序来理解调用栈。

#include <iostream> int add(int a, int b) { int sum = a + b; return sum; } int calc(int x) { int y = x * 2; return add(y, 10); } int work(int n) { int value = n + 1; return calc(value); } int main() { int data = 3; int ret = work(data); std::cout << "ret = " << ret << std::endl; return 0; }

这个程序的调用关系是:

main -> work -> calc -> add

也就是 4 层函数调用。

将程序编译完成后,通过gdb启动,在add函数处设置断点,并通过bt命令查看当前的函数栈调用。如下图所示

这个输出表示:

栈帧函数含义
#0add(a=8, b=10)当前程序停在add函数中,在test.cpp源文件的第5行
#1calc(x=4)add是由calc调用的,在test.cpp源文件的第12行
#2work(n=3)calc是由work调用的,在test.cpp源文件的第18行
#3main()work是由main调用的,在test.cpp源文件的第24行