一、GDB入门:从零开始认识这个调试利器
说实话,我接触GDB已经十几年了。刚入行那会儿,总觉得调试就是printf大法,直到有一次线上崩溃问题折腾了我整整三天——嗯,从那以后我就老老实实学GDB了。
GDB是什么?全称GNU Debugger,是Linux下最经典的调试工具。没有图形界面,全靠命令行。但你别小看它,它比任何IDE调试器都强大。我个人的习惯是:写代码用IDE,调试必开GDB。
GDB能做什么?
说白了,GDB能帮你回答三个问题:
- 程序在哪儿崩了?——定位段错误、非法指令
- 变量值是什么?——查看内存、寄存器、堆栈
- 执行流程怎么走的?——单步跟踪、断点控制
我在项目中遇到过最典型的场景:一个服务跑着跑着就挂了,日志里啥也没有。用GDB attach上去,等它再崩的时候,backtrace一看,哦,野指针。这种问题printf根本查不出来。
核心能力一览:
| 功能 | 说明 | 常用命令 |
|---|---|---|
| 断点调试 | 在指定行/函数暂停 | break, watch |
| 单步执行 | 逐行/逐指令运行 | step, next, stepi |
| 变量查看 | 打印变量、内存、寄存器 | print, x, info registers |
| 堆栈回溯 | 查看函数调用链 | backtrace, frame |
| 条件断点 | 满足条件才触发 | break if |
GDB的安装与启动
安装其实很简单。大多数Linux发行版都自带,如果没有:
# Ubuntu/Debian
sudo apt-get install gdb
# CentOS/RHEL
sudo yum install gdb
# 验证安装
gdb --version
启动方式有三种,你想想看哪种适合你:
- 直接调试:
gdb ./myprogram—— 最常用 - 附加进程:
gdb -p 12345—— 调试正在运行的程序 - 分析core文件:
gdb ./myprogram core.12345—— 事后分析崩溃
我的小技巧:调试前记得编译时加 -g 选项。不加的话,你看到的全是汇编,那酸爽...我曾经吃过这个亏,编译脚本里忘了加-g,调试了一下午全是问号。
基本命令概览
刚开始学GDB,你不需要记住所有命令。记住这几个就够了:
# 启动与退出
gdb ./a.out # 启动
quit # 退出(或Ctrl+D)
# 运行控制
run # 运行程序
start # 运行并停在main函数
continue # 继续执行(简写c)
# 断点操作
break main # 在main函数设断点(简写b)
break 42 # 在第42行设断点
info breakpoints # 查看所有断点
delete 1 # 删除编号1的断点
# 单步调试
step # 进入函数内部(简写s)
next # 跳过函数(简写n)
finish # 执行完当前函数
# 查看信息
print var # 打印变量值(简写p)
backtrace # 查看调用栈(简写bt)
list # 查看源代码(简写l)
为什么会这样设计?因为GDB的哲学是:常用命令越短越好。你想想看,调试的时候谁有功夫打完整单词?所以b、c、n、s这些单字母命令,用熟了效率极高。
注意:GDB默认使用AT&T汇编语法。如果你习惯Intel语法,可以在~/.gdbinit里加上 set disassembly-flavor intel。我个人的习惯是用Intel,看着顺眼。
知识体系总览
下面这张图是我自己整理的GDB入门知识结构,你可以照着这个路径学习:
这张图把GDB入门拆成了四个模块。我个人建议的学习顺序是:先搞懂GDB能做什么,再装好环境,然后照着基本命令练一遍。别贪多,一天学会run、break、next、print这四个命令,你就已经能解决大部分问题了。
一句话总结:GDB就是程序员的显微镜。printf只能看到你想看的,GDB能看到你没想过的。
好了,这一章就到这里。记住,调试不是写代码的附属品,它是开发的一部分。早点学会GDB,你写代码的底气都会不一样。