GDB作为强大的调试工具,在嵌入式开发、RTOS、Linux系统调试中均有广泛应用,其灵活性和免费特性使其成为开发者的首选。
1 条件断点技巧
条件断点是GDB的核心功能之一,允许在特定条件满足时触发断点,显著提升调试效率。
1.1 条件断点设置
设置条件断点的基本语法:
(gdb) break <location> if <condition>
示例:
(gdb) b sum.c:10 if i == 5
条件断点的特点:
- 仅当条件表达式为真(非零)时触发
- 条件表达式可以是有效的C/C++表达式
- 可使用程序中的变量和函数调用
1.2 为现有断点添加条件
使用condition命令为已设断点添加条件:
(gdb) condition <breakpoint number> <expression>
示例:
(gdb) condition 1 i > 10
这在调试循环中的特定场景时非常有用。
1.3 忽略断点次数
ignore命令允许断点在触发前忽略指定次数:
(gdb) ignore <breakpoint number> <count>
示例:
(gdb) ignore 1 5
应用场景包括跳过循环前几次迭代或避免频繁断点停止。
1.4 断点命令列表
GDB支持为断点定义命令列表,触发时自动执行:
(gdb) break <location>
(gdb) commands <breakpoint number>
> command1
> command2
> end
示例:设置断点并自动打印变量后继续执行。
2 观察点Watchpoint的使用
观察点用于监控变量或表达式的值变化,是调试内存问题的利器。
2.1 观察点类型
GDB支持三种观察点:
- 写观察点:
watch <expression>,值改变时触发
- 读观察点:
rwatch <expression>,被读取时触发
- 访问观察点:
awatch <expression>,读取或写入时触发
2.2 观察点使用示例
假设调试数组越界访问:
int buffer[10];
for (int i = 0; i <= 10; i++) {
buffer[i] = i; // 越界访问buffer[10]
}
设置观察点:
(gdb) watch buffer[10]
运行程序,当buffer[10]被访问时暂停,使用info watchpoints查看状态。
2.3 观察点的限制
- 硬件观察点数量有限(通常4个)
- 软件观察点影响性能
- 某些数据类型可能不支持硬件观察点
3 多线程调试
多线程程序调试复杂,GDB提供专门功能,尤其适用于并发编程场景。
3.1 线程相关命令
- 查看所有线程:
info threads
- 切换线程:
thread <thread-id>
- 对所有线程执行命令:
thread apply all <command>
- 线程特定断点:
break <location> thread <thread-id>
3.2 线程调度控制
使用set scheduler-locking <mode>控制调度:
off:默认,所有线程自由运行
on:仅当前线程运行
step:单步时自动锁定
例如,调试时设置set scheduler-locking on避免其他线程干扰。
4 信号处理调试
GDB支持调试UNIX信号处理。
4.1 查看信号处理
info signals:显示所有信号处理方式
info signal SIGINT:查看特定信号
4.2 捕获信号
使用handle <signal> <action>捕获信号,如:
(gdb) handle SIGSEGV stop
动作包括stop、noprint、nostop等。
4.3 生成信号
主动发送信号:signal <signal>,例如signal SIGINT。
5 远程调试
GDB远程调试通过gdbserver实现,适用于嵌入式或跨网络环境。
5.1 远程调试架构
- 目标机运行gdbserver和被调试程序
- 主机运行GDB,通过网络连接
5.2 启动gdbserver
在目标机:
gdbserver <host:port> <program> [arguments]
示例:gdbserver :1234 ./my_program
5.3 连接到远程目标
在主机:
(gdb) target remote <host:port>
例如:target remote 192.168.1.100:1234
5.4 交叉调试
嵌入式开发中常用,使用交叉编译器和对应GDB版本。
6 内存调试技巧
内存问题调试困难,GDB提供辅助功能。
6.1 内存查看技巧
- 查看内存:
x/20xb buffer
- 查看动态内存:
p *(int *)0x600850
6.2 内存泄漏检测
GDB间接支持,推荐使用Valgrind等工具。
6.3 缓冲区溢出调试
步骤:设置观察点、分析调用栈(bt)、查看内存状态。