别再只会gdb test了Ubuntu下从编译到调试的完整实战指南附常用命令速查表在Ubuntu环境下开发C/C程序时gdb调试器是每个开发者必须掌握的利器。但很多开发者仅仅停留在gdb test这样的基础用法上无法充分发挥gdb的强大功能。本文将带你从编译阶段开始构建一套完整的调试工作流让你从会用进阶到用好gdb。1. 编译阶段的调试准备1.1 正确的编译姿势调试的第一步其实在编译阶段就已经开始了。很多开发者遇到的第一个困惑就是为什么我的断点不起作用这通常是因为编译时没有包含调试信息。在Ubuntu下使用g编译时必须添加-g选项g -g main.cpp -o myapp这个-g选项会告诉编译器在可执行文件中嵌入调试符号表。有趣的是你可以通过-g3获取更详细的调试信息g -g3 main.cpp -o myapp_with_more_info提示调试信息会增加可执行文件的大小但不会影响程序性能。建议在开发阶段始终使用-g选项。1.2 优化级别与调试另一个常见问题是为什么我的变量值显示不正确这可能是因为开启了编译器优化。不同优化级别对调试的影响优化级别对调试的影响-O0无优化最适合调试-O1基本优化可能影响变量观察-O2中等优化可能改变代码执行顺序-O3激进优化可能导致严重调试困难建议调试时使用g -g -O0 main.cpp -o myapp_debug2. 高效启动调试会话2.1 启动方式的智能选择大多数开发者只知道gdb myapp这种基础启动方式但实际上gdb提供了多种启动选项# 直接启动程序 gdb -ex break main -ex run --args ./myapp arg1 arg2 # 调试正在运行的进程 gdb -p $(pidof myapp) # 调试core dump文件 gdb ./myapp core2.2 配置文件.gdbinit在用户主目录或项目目录下创建.gdbinit文件可以预设常用命令# ~/.gdbinit 示例 set pagination off set history save on define pp print $arg0 end这样每次启动gdb时都会自动加载这些配置极大提升效率。3. 断点管理的艺术3.1 条件断点的妙用条件断点是调试循环时的神器。假设我们有一个循环for(int i0; i100; i) { // 我们只想在i50时中断 process(i); }设置条件断点(gdb) break process if i50更复杂的条件也是可以的(gdb) break process if strcmp(name, target)03.2 断点的高级管理查看所有断点(gdb) info break临时禁用断点(gdb) disable 2-5 # 禁用编号2到5的断点断点命中计数(gdb) ignore 3 10 # 忽略断点3的前10次命中4. 变量监控与内存检查4.1 display的自动化监控display命令可以自动在每次程序停止时显示变量值(gdb) display/i $pc # 以指令格式显示程序计数器 (gdb) display/x $rax # 以十六进制显示rax寄存器查看当前display列表(gdb) info display4.2 内存检查技巧检查内存区域(gdb) x/20xb array # 以十六进制字节查看数组前20字节 (gdb) x/10dw buffer # 以十进制字查看缓冲区前10个字检查结构体(gdb) p *my_struct (gdb) p/x *my_struct # 以十六进制显示5. 高效调试连招5.1 常见调试场景的快捷键组合快速定位崩溃点(gdb) r (gdb) bt单步调试组合(gdb) start (gdb) n 3 # 执行3步 (gdb) s # 进入函数循环调试技巧(gdb) b 45 # 循环开始行 (gdb) commands silent p i c end5.2 自定义命令在gdb中可以定义自己的命令(gdb) define memdump x/16xb $arg0 end然后就可以使用(gdb) memdump 0x7fffffffdcc06. 多线程调试技巧调试多线程程序时这些命令特别有用查看所有线程(gdb) info threads切换线程(gdb) thread 2锁定当前线程(gdb) set scheduler-locking on7. 常用命令速查表类别命令说明启动gdb -tui program带图形界面启动断点b *0x400522在内存地址设置断点数据p/x global_var以十六进制打印变量地址寄存器info registers查看所有寄存器值调用栈bt full显示完整调用栈和局部变量观察点watch var变量改变时中断反汇编disassemble main反汇编main函数信号handle SIGSEGV stop捕获段错误信号8. 实战案例调试段错误启用core dumpulimit -c unlimited echo core.%e.%p /proc/sys/kernel/core_pattern运行程序产生core dump后gdb ./myapp core.myapp.1234查看崩溃点(gdb) bt (gdb) frame 2 (gdb) p *pointer9. 性能分析技巧gdb也可以用于基本性能分析(gdb) set logging file profile.txt (gdb) set logging on (gdb) while 1 step info registers end (gdb) set logging off10. 高级技巧Python扩展gdb支持Python扩展可以编写强大的调试脚本class MyBreakpoint(gdb.Breakpoint): def stop(self): val gdb.parse_and_eval(variable) print(fVariable value: {val}) return False MyBreakpoint(main.c:42)保存为script.py后在gdb中(gdb) source script.py