1. GDB基础断点设置与程序控制

任务目标

使用GDB在main函数入口设置断点,启动程序后通过单步执行(next/step)跟踪代码流,并观察局部变量在每条语句执行后的值变化,掌握GDB最基本的调试循环:设断点 → 运行 → 单步 → 查变量。

环境与准备

  • Linux环境,已安装gcc与gdb(检查命令:gcc --version、gdb --version)。
  • 编译时必须加-g选项生成调试符号,否则GDB无法关联源码行与变量名。

示例程序

创建文件demo.c,内容如下。该程序包含一个简单的循环累加与函数调用,便于演示断点、单步与变量观察。

```c #include int add(int a, int b) { int sum = a + b; return sum; } int main() { int x = 10; int y = 20; int result = 0; for (int i = 0; i < 3; i++) { result = add(x + i, y); printf("i=%d, result=%d\n", i, result); } return 0; } ```

编译与启动GDB

在终端执行以下命令编译并启动调试会话:

```bash gcc -g -o demo demo.c gdb ./demo ```

进入GDB交互界面后,按顺序执行下列命令完成整个调试闭环:

  1. 设置断点:break main(或简写b main),在main函数入口暂停。
  2. 运行程序:run(或简写r),程序启动后停在main第一行。
  3. 单步执行:next(或n)逐行执行,遇到函数调用时不进入;step(或s)则会进入函数内部。
  4. 观察变量:print x(或p x)查看当前值;info locals一次性查看当前作用域所有局部变量。
  5. 继续运行:continue(或c)运行到下一个断点或程序结束。

完整调试会话示例

以下为一次完整的GDB交互过程((gdb)为提示符,其后为输入命令):


(gdb) break main
Breakpoint 1 at 0x1149: file demo.c, line 9.
(gdb) run
Starting program: /path/to/demo

Breakpoint 1, main () at demo.c:9
9           int x = 10;
(gdb) next
10          int y = 20;
(gdb) print x
$1 = 10
(gdb) next
11          int result = 0;
(gdb) print y
$2 = 20
(gdb) next
13          for (int i = 0; i < 3; i++) {
(gdb) next
14              result = add(x + i, y);
(gdb) step
add (a=10, b=20) at demo.c:4
4           int sum = a + b;
(gdb) print a
$3 = 10
(gdb) print b
$4 = 20
(gdb) next
5           return sum;
(gdb) print sum
$5 = 30
(gdb) next
6       }
(gdb) next
main () at demo.c:15
15          printf("i=%d, result=%d\n", i, result);
(gdb) print result
$6 = 30
(gdb) continue
i=0, result=30
i=1, result=31
i=2, result=32
[Inferior 1 (process 12345) exited normally]

注意:上述$1、$2等是GDB为每次print结果自动分配的编号,实际值取决于当前执行位置。第3次循环时i=2,因此add(12, 20)返回32,与输出一致。

验证方法与通过标准

  • 程序能正常编译并启动GDB,break main成功设置断点。
  • run后程序停在main函数第一行(源码第9行),而非直接运行结束。
  • 使用next逐行执行时,每执行一行,print对应变量能观察到符合代码逻辑的值变化(如x初始化为10,y为20)。
  • 在result = add(x + i, y);处使用step能进入add函数内部,且能查看参数a、b和局部变量sum的值。
  • 最终continue后程序正常退出,输出三行i=0..2的结果,且数值与代码逻辑一致(30、31、32)。

常见问题

  • 提示“No symbol table is loaded”:编译时忘记加-g,重新用gcc -g -o demo demo.c编译。
  • next直接跳过函数调用:这是正常行为,next不进入子函数;如需进入函数内部观察参数和局部变量,应改用step。
  • print变量提示“No symbol”:当前执行行不在该变量的作用域内(例如在add函数中打印main的局部变量x),需先finish退出函数或up切换栈帧。