gdb教程(4): 函数调用栈

通过查看函数调用栈,我们可以从整体上了解程序执行的状态,并且更容易发现程序中的问题。本片文章介绍gdb关于函数调用栈的操作。

相关文章

gdb教程(1):如何开始
gdb教程(2):控制程序的执行
gdb教程(3):断点(breakpoint)和观察点(watchpoint)
gdb教程(4):函数调用栈

查看函数调用栈

使用命令backtrace(简写bt)来查看函数调用栈

(gdb) backtrace
#0 func2 (x=30) at test.c:5
#1 0x80483e6 in func1 (a=30) at test.c:10
#2 0x8048414 in main (argc=1, argv=0xbffffaf4) at test.c:19
#3 0x40037f5c in __libc_start_main () from /lib/libc.so.6
(gdb)

从上面的例子,我们可以发现:当前程序正在执行函数func2(),而函数func2()在函数func1(a=30)内被调用,相关的代码的位置在test.c:19

切换函数栈帧

设想这么一个情况,对于上面提到的例子,我们发现func2()中的错误是由于func1()中传入了错误的参数导致的,现在希望可以看func1()中的错误现场。

对于这样的需求,可以使用gdb命令frame加上函数栈帧的编号来实现,函数栈帧的编号指的是每一个函数栈帧前面以#开头的编号了,例如我想要将当前栈帧从func2()切换到func1(),那么我只要执行如下命令。

(gdb) frame 2
#2 0x8048414 in main (argc=1, argv=0xbffffaf4) at test.c:19
19 x = func1(x);
(gdb)

frame 2表示切换到编号为2的栈帧,现在我们已经成功切换到func1()栈帧中了,我们可以使用print或者set来查看或修改变量的值。

查看当前函数栈的情况

使用info frame来查看当前函数栈的基础信息

(gdb) info frame
Stack level 2, frame at 0xbffffa8c:
eip = 0x8048414 in main (test.c:19); saved eip 0x40037f5c
called by frame at 0xbffffac8, caller of frame at 0xbffffa5c
source language c.
Arglist at 0xbffffa8c, args: argc=1, argv=0xbffffaf4
Locals at 0xbffffa8c, Previous frame's sp is 0x0
Saved registers:
ebp at 0xbffffa8c, eip at 0xbffffa90

使用info locals来查看当前函数内所有变量的值

(gdb) info locals
x = 30
s = 0x8048484 "Hello World!\n"

使用info args来查看当前函数的参数以及他们的值

(gdb) info args
argc = 1
argv = (char **) 0xbffffaf4

参考资料

RMS’s gdb Tutorial: How do I use the call stack?

此文有用? 求鼓励!

显示 Gitment 评论