GDB 超全详解教程:零基础入门到高阶调试
一、GDB 简介与核心作用
GDB(GNU Debugger)是 GNU 开源组织推出的跨平台、命令行式程序调试工具,支持 C/C++、Go、Rust 等主流编译型语言,可运行在 Linux、MacOS、类 Unix 系统,是后端开发、嵌入式开发、底层调试的核心工具。
相较于 IDE 图形化调试,GDB 轻量化、无依赖、可远程调试、支持内核级调试,能够实现:程序启动调试、断点调试、堆栈分析、变量监控、内存查看、异常捕获、进程附着调试等全场景调试能力,是排查段错误、死循环、内存越界、堆栈溢出等疑难问题的必备工具。
二、前置准备:编译带调试信息的程序
2.1 编译参数说明
GDB 只能调试带调试符号信息的程序,普通编译(gcc main.c -o main)会剥离调试信息,无法断点、查看源码。
核心编译参数:
-g:添加基础调试信息,支持源码级调试(最常用)
-ggdb:生成 GDB 专用调试信息,兼容性最好,推荐使用
-O0:关闭编译器优化(默认 O2/O3 优化会打乱代码执行顺序,导致调试错位)
标准编译命令:gcc main.c -o main -ggdb -O0
2.2 实战示例代码(全程调试使用)
编写main.c,包含循环、函数调用、数组越界、指针操作,覆盖绝大多数调试场景:
#include <stdio.h> #include <string.h> // 加法函数 int add(int a, int b) { int res = a + b; return res; } // 循环测试函数 void loop_test() { int arr[5] = {1,2,3,4,5}; // 故意制造数组越界(段错误隐患) for(int i = 0; i <= 5; i++) { arr[i] = i * 2; printf("arr[%d] = %d\n", i, arr[i]); } } int main(int argc, char *argv[]) { int x = 10; int y = 20; int sum = add(x, y); printf("sum = %d\n", sum); loop_test(); char str[4] = "abc"; char *p = str; printf("str = %s\n", p); return 0; }编译命令:gcc main.c -o gdb_demo -ggdb -O0,生成可调试程序gdb_demo。
三、GDB 调试整体流程图
完整调试链路:启动 GDB → 配置参数 → 设置断点 → 运行程序 → 单步调试 → 查看变量/堆栈 → 动态修改变量 → 排查异常 → 退出调试
四、GDB 全量命令分类详解(含简写+示例)
本文将 GDB 所有常用命令按启动配置、断点管理、程序运行、单步调试、信息查看、堆栈分析、内存操作、动态修改、高级调试、退出配置十大类整理,全覆盖日常调试场景。
4.1 启动与基础配置命令
用于启动 GDB、配置程序运行参数、日志、工作环境。
完整命令 | 简写 | 功能说明 | 实操示例 |
|---|---|---|---|
gdb [程序名] | 无 | 启动GDB,加载可执行程序 |
|
set args [参数] | 无 | 设置程序命令行参数 |
|
show args | 无 | 查看已设置的命令行参数 |
|
set verbose on/off | 无 | 开启/关闭详细调试日志 |
|
directory [路径] | dir | 添加源码搜索路径 |
|
help [命令] | h | 查看命令帮助文档 |
|
quit | q | 退出GDB调试 |
|
4.2 断点管理命令(核心高频)
断点是调试核心,支持行断点、函数断点、条件断点、临时断点、观察断点(监控变量/内存变化)。
完整命令 | 简写 | 功能说明 | 实操示例 |
|---|---|---|---|
break [行号] | b | 在指定行设置断点 |
|
break [函数名] | b | 在函数入口设置断点 |
|
break [文件:行号] | b | 多文件项目指定文件断点 |
|
break +n/-n | b | 当前行前后n行断点 |
|
tbreak [位置] | tb | 临时断点(触发1次后自动删除) |
|
break [位置] if [条件] | b | 条件断点(满足条件才触发) |
|
watch [变量] | w | 写观察断点(变量被修改触发) |
|
rwatch [变量] | rw | 读观察断点(变量被读取触发) |
|
awatch [变量] | aw | 读写观察断点(读/改均触发) |
|
info breakpoints | i b | 查看所有断点列表 |
|
delete [断点号] | d | 删除指定断点,无参数删除全部 |
|
disable [断点号] | dis | 禁用断点(保留不删除) |
|
enable [断点号] | ena | 启用禁用的断点 |
|
4.3 程序运行与继续命令
控制程序启动、暂停、重启、继续运行。
完整命令 | 简写 | 功能说明 | 实操示例 |
|---|---|---|---|
run | r | 从头运行程序,触发断点暂停 |
|
continue | c | 暂停后继续运行到下一个断点 |
|
start | 无 | 启动程序,暂停在main函数第一行 |
|
kill | k | 终止当前正在调试的程序 |
|
restart | rs | 重启程序调试 |
|
4.4 单步调试命令(逐行执行)
精准控制代码执行流程,区分进入函数和跳过函数,是逐行排错核心。
完整命令 | 简写 | 功能说明 | 适用场景 |
|---|---|---|---|
step | s | 逐行执行,进入自定义函数内部 | 需要调试函数内部逻辑 |
next | n | 逐行执行,跳过函数,不进入内部 | 确认函数无问题,快速跳过 |
finish | fin | 执行完当前函数,跳出到函数调用处 | 误入无需调试的函数,快速退出 |
until | u | 运行到指定行,或跳出循环体 | 跳出死循环、快速跑完循环 |
核心区别:s会进入函数,n直接执行完函数返回结果,不进入内部。
4.5 源码查看命令
调试过程中实时查看源码,无需退出 GDB。
命令 | 简写 | 功能 | 示例 |
|---|---|---|---|
list | l | 查看当前行上下10行源码 |
|
list 行号 | l | 查看指定行附近源码 |
|
list 函数名 | l | 查看指定函数源码 |
|
set listsize N | 无 | 设置list显示行数 |
|
4.6 变量与表达式查看命令
调试最常用命令,用于查看变量、数组、指针、表达式运算结果。
命令 | 简写 | 功能 | 示例 |
|---|---|---|---|
print [变量/表达式] | p | 打印变量值、运算表达式 |
|
print /x 变量 | p/x | 十六进制打印 |
|
print /d 变量 | p/d | 十进制打印(默认) |
|
print /c 变量 | p/c | 字符格式打印 |
|
display [变量] | disp | 每次暂停自动打印变量 |
|
undisplay [编号] | undisp | 取消自动打印 |
|
info locals | i lo | 查看当前函数所有局部变量 |
|
info args | i ar | 查看当前函数参数 |
|
4.7 堆栈调试命令(排查崩溃核心)
程序段错误、崩溃时,通过堆栈查看函数调用链路,定位崩溃代码行。
命令 | 简写 | 功能 | 示例 |
|---|---|---|---|
backtrace | bt | 查看完整堆栈调用链路 |
|
bt N | bt N | 只查看顶部N层堆栈 |
|
frame [堆栈号] | f | 切换到指定堆栈帧 |
|
up | 无 | 切换到上一层堆栈 |
|
down | 无 | 切换到下一层堆栈 |
|
4.8 内存与指针调试命令
查看内存数据、指针指向、数组内存,排查内存越界、野指针问题。
命令 | 功能说明 | 示例 |
|---|---|---|
x /[格式][长度] 地址 | 查看指定内存数据 |
|
print *指针 | 解引用指针,查看指向数据 |
|
info memory | 查看程序内存布局 |
|
x命令格式详解:x/数量 格式 宽度 地址
格式:
d十进制、x十六进制、c字符、s字符串宽度:
b字节、w4字节、g8字节
4.9 动态修改变量与运行时修改
无需重新编译,实时修改变量值,快速验证逻辑。
命令 | 功能 | 示例 |
|---|---|---|
set 变量=值 | 修改变量值 |
|
set ptr=地址 | 修改指针指向 |
|
4.10 高阶调试命令
4.10.1 附着正在运行的进程
无需重启程序,调试正在后台运行的进程(排查死循环、卡死问题)。
# 1. 查看进程PID ps -ef | grep gdb_demo # 2. 附着进程 gdb attach 进程PID # 3. 调试完成后分离进程(不杀死进程) detach4.10.2 核心转储文件调试(崩溃复盘)
程序崩溃生成 core 文件后,通过 GDB 复盘崩溃现场:
# 开启core文件生成 ulimit -c unlimited # 调试core文件 gdb ./gdb_demo core.xxx4.10.3 日志与批量调试
save breakpoints 文件名:保存所有断点到文件source 文件名:加载保存的断点配置set logging on:开启GDB日志,保存调试过程
五、完整实战调试流程(手把手演示)
5.1 启动调试+设置断点
# 启动gdb gdb ./gdb_demo # 在add函数、loop_test函数设置断点 (gdb) b add (gdb) b loop_test # 查看断点 (gdb) i b # 运行程序 (gdb) r5.2 逐行调试与变量查看
# 触发add函数断点,查看函数参数 (gdb) i ar # 单步执行 (gdb) s # 查看局部变量res (gdb) p res # 跳出当前函数 (gdb) fin # 继续运行到下一个断点 (gdb) c5.3 条件断点排查数组越界
# 在循环行设置条件断点,i=5时暂停(越界位置) (gdb) b 25 if i==5 (gdb) c # 查看数组内存 (gdb) x/6dw arr # 修改变量规避错误,验证逻辑 (gdb) set i=4 # 继续运行 (gdb) c5.4 堆栈崩溃排查演示
程序因数组越界触发段错误后:
# 查看崩溃堆栈 (gdb) bt # 切换到崩溃堆栈帧 (gdb) f 0 # 查看当前变量 (gdb) i lo可精准定位到i=5时数组越界的问题。
六、高频问题与调试技巧
6.1 调试错位问题
现象:断点行和执行行不匹配,原因:编译器优化,解决方案:编译必须加-O0 -ggdb。
6.2 找不到源码问题
解决方案:使用dir 源码路径添加源码搜索目录。
6.3 重复调试快捷操作
回车:重复执行上一条命令
r:一键重启调试,无需退出GDB保存断点:避免每次重启重新设置断点
GDB 调试核心逻辑可总结为:断点精准定位、单步逐行排查、变量实时监控、堆栈回溯溯源、动态修试验证。本文覆盖了 GDB 全部高频、高阶命令,搭配可直接运行的示例代码和完整调试流程,能够满足日常开发、嵌入式调试、崩溃排错等所有场景。
熟练掌握 GDB 可快速定位段错误、内存越界、死循环、逻辑异常等疑难问题,是程序员必备的底层调试能力。
