3 调用堆栈-call stack

调用堆栈是什么

调用堆栈是我们找到能够控制程序流的堆栈帧.
当一个函数被调用时,它会创建一个堆栈帧,告诉计算机如何在完成执行后将控制权返回给调用者。
堆栈帧也是“存储”局部变量和函数参数的地方.
我们可以通过堆栈帧来确定程序是如何运行的.
在当前帧下的堆栈列表就叫做 回溯(backtrace).

3.1 如何获取回溯?

使用 backtrace 来获取调用栈.
这个例子中:

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

3.2 如何改变堆栈帧?

使用 frame 命令. 每个堆栈帧前面都有一个数字. 所以 frame 这个命令可以接收一个数字作为参数.

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

3.3 如何检查堆栈帧?

To look at the contents of the current frame, there are 3 useful gdb commands. info frame displays information about the current stack frame. info locals displays the list of local variables and their values for the current stack frame, and info args displays the list of arguments.
有3个 gdb 命令可以检查当前的堆栈帧:

  • info frame 展示关于当前堆栈的信息;
  • info locals 显示当前堆栈帧的局部变量和局部变量值;
  • info args 显示的是参数列表 ``` (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

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

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