1. GDB入门:GDB是什么、GDB能做什么、GDB的安装与启动、GDB的基本调试流程
1.1 GDB到底是什么?
GDB,全称GNU Project Debugger。说白了,就是一个让你能「看穿」程序运行过程的工具。
我刚开始学嵌入式那会儿,调试全靠printf。代码里到处塞打印语句,编译、下载、看串口输出,改一行代码就得重复一遍流程。效率低不说,还经常漏掉关键信息。后来老同事甩给我一句:「别折腾了,学学GDB吧。」
嗯,从那以后,我再也没回到printf调试的老路上。
GDB能让你做到三件事:
- 让程序停下来 —— 在你想观察的位置暂停执行
- 查看程序的状态 —— 变量值、寄存器、内存、堆栈,一目了然
- 改变程序的走向 —— 修改变量、跳过函数、甚至直接修改返回地址
你想想看,这比printf强了多少倍?
1.2 GDB能做什么?
我列几个最常用的场景,都是我在项目中实际遇到过的:
| 场景 | GDB能做的事 |
|---|---|
| 程序崩溃(段错误) | 查看崩溃时的堆栈、寄存器、变量值 |
| 逻辑错误 | 单步执行,观察变量变化,找到逻辑漏洞 |
| 死循环 | 暂停程序,查看当前执行位置和循环变量 |
| 内存泄漏 | 配合工具查看堆内存分配情况 |
| 多线程问题 | 切换线程,查看各线程的堆栈和变量 |
说白了,只要你的程序能跑起来,GDB就能帮你把它「解剖」开。
1.3 GDB的安装与启动
安装GDB其实很简单。我习惯用包管理器直接装:
# Ubuntu / Debian
sudo apt-get install gdb
# CentOS / RHEL
sudo yum install gdb
# macOS (Homebrew)
brew install gdb
装完之后,验证一下:
gdb --version
看到版本号就说明装好了。
启动GDB有两种方式:
- 直接启动:
gdb ./myprogram—— 加载可执行文件 - 附加到进程:
gdb -p 1234—— 调试正在运行的程序(1234是进程ID)
我个人更常用第一种。先编译好程序,然后直接gdb加载。注意编译时要加-g选项,否则GDB看不到源码和变量名:
gcc -g -o myprogram myprogram.c
注意: 我曾经遇到过编译时忘了加
-g,结果GDB里全是地址,变量名一个都看不到。排查了半天才发现是编译选项的问题。所以,-g一定要加上。
1.4 GDB的基本调试流程
咱们用一个最简单的例子走一遍流程。假设有这么一个程序:
// test.c
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
int x = 10;
int y = 20;
int result = add(x, y);
printf("Result: %d\n", result);
return 0;
}
编译:
gcc -g -o test test.c
启动GDB:
gdb ./test
进入GDB界面后,你会看到类似这样的提示符:
(gdb)
基本调试流程就四步:
- 设置断点 —— 告诉GDB在哪里停下来
- 运行程序 —— 让程序跑起来
- 查看状态 —— 程序停住后,检查变量、堆栈
- 继续或单步 —— 一步步执行,或者直接跑到下一个断点
实际操作一下:
(gdb) break main # 在main函数入口设断点
(gdb) run # 运行程序,会在main处停住
(gdb) print x # 查看变量x的值
$1 = 10
(gdb) print y # 查看变量y的值
$2 = 20
(gdb) next # 单步执行,跳过add函数调用
(gdb) print result # 查看result的值
$3 = 30
(gdb) continue # 继续运行,直到程序结束
你看,整个过程非常直观。程序停住后,你可以随意查看任何变量。这就是GDB的魅力所在。
小技巧: 我习惯在调试时先用
list命令看看当前附近的源码,确认自己停在了正确的位置。list默认显示10行代码,非常方便。
1.5 本章知识体系
下面这张图总结了GDB入门阶段的核心逻辑:
这张图把GDB入门阶段的核心内容串起来了。你记住一个核心思想就行:GDB就是让你能「看穿」程序的工具。后面的所有章节,都是围绕这个核心展开的。
本章要点回顾:
- GDB是GNU调试器,用于观察和控制程序运行
- 能暂停程序、查看状态、改变走向
- 安装简单,启动方式有两种
- 基本流程:设断点 → 运行 → 查看 → 继续
- 编译时务必加
-g选项
好了,第一章就到这里。记住这些基础操作,后面咱们再深入条件断点的各种玩法。