1. GDB基础断点设置与程序控制
任务目标
使用GDB在main函数入口设置断点,启动程序后通过单步执行(next/step)跟踪代码流,并观察局部变量在每条语句执行后的值变化,掌握GDB最基本的调试循环:设断点 → 运行 → 单步 → 查变量。
环境与准备
- Linux环境,已安装
gcc与gdb(检查命令:gcc --version、gdb --version)。 - 编译时必须加
-g选项生成调试符号,否则GDB无法关联源码行与变量名。
示例程序
创建文件demo.c,内容如下。该程序包含一个简单的循环累加与函数调用,便于演示断点、单步与变量观察。
编译与启动GDB
在终端执行以下命令编译并启动调试会话:
```bash gcc -g -o demo demo.c gdb ./demo ```进入GDB交互界面后,按顺序执行下列命令完成整个调试闭环:
- 设置断点:
break main(或简写b main),在main函数入口暂停。 - 运行程序:
run(或简写r),程序启动后停在main第一行。 - 单步执行:
next(或n)逐行执行,遇到函数调用时不进入;step(或s)则会进入函数内部。 - 观察变量:
print x(或p x)查看当前值;info locals一次性查看当前作用域所有局部变量。 - 继续运行:
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切换栈帧。