Linux 调试神器 gdb / cgdb 实战指南
(从零基础到生产环境能用得上,2025–2026 年仍然最实用的内容)
先回答最核心的三个问题
- gdb 和 cgdb 有什么本质区别?
gdb → 纯命令行(功能最全,但交互体验差)
cgdb → gdb 的前端(在终端里提供类似 vim 的界面 + 代码高亮 + 分屏) - 什么时候用 gdb,什么时候用 cgdb?
- 只用 gdb:远程调试、核心 dump 分析、脚本自动化、容器内无图形界面
- 优先 cgdb:本地开发、本机有终端、需要频繁看源代码、单步跟踪逻辑
- 现代替代品已经很多了,为什么还要学 gdb/cgdb?
因为在以下场景中,gdb 仍然无可替代(或性价比最高):
- 核心 dump 分析(线上崩溃)
- 多线程死锁/竞争
- 信号处理异常
- 远程调试(ssh + gdbserver)
- 没有 IDE 的环境(容器、嵌入式、老服务器)
- 需要极致控制(汇编级、寄存器、内存)
一、最快上手 cgdb(推荐新手第一步)
安装(主流发行版)
# Ubuntu/Debian
sudo apt install cgdb
# CentOS/RHEL/Fedora
sudo dnf install cgdb 或 sudo yum install cgdb
# Arch
sudo pacman -S cgdb
最常用启动方式(带源码调试)
# 编译时一定要加 -g (最好再加 -O0)
gcc -g -O0 -o test test.c
# 方式1:最推荐
cgdb ./test
# 方式2:带参数
cgdb --args ./test arg1 arg2
# 方式3:附加到已运行进程
cgdb -p <pid>
cgdb 界面快捷键速查(必须记住前 8 个)
| 按键 | 作用 | 备注 |
|---|---|---|
| F5 | 运行到 main(或继续) | 最常用 |
| F6 | 下一行(next) | 不进入函数 |
| F7 | 单步进入(step) | 进入函数内部 |
| F8 | 跳出当前函数(finish) | 非常实用 |
| Ctrl + L | 刷新屏幕(界面乱了按这个) | 经常需要 |
| : | 进入 gdb 命令模式 | 想输入复杂命令时 |
| q | 退出 cgdb | — |
| Ctrl + x Ctrl + a | 切换焦点(代码窗口 ↔ 命令窗口) | 很重要! |
| b 行号/函数名 | 设置断点 | b main / b 42 / b func |
| c | continue(继续执行) | — |
| r | run(从头重新运行) | — |
二、gdb 核心命令分层速查表(生产最常用)
1. 程序启动与退出类
(gdb) run [参数] # 启动程序(r / run)
(gdb) run < input.txt # 重定向输入
(gdb) kill # 杀死当前被调试程序
(gdb) quit # 退出 gdb
2. 断点管理(最核心)
b main # 在 main 函数入口设置断点
b file.c:123 # 指定文件 + 行号
b func if x > 10 # 条件断点
info breakpoints # 查看所有断点(i b)
delete 1 # 删除 1 号断点
clear main # 清除 main 处的断点
disable 2 # 禁用 2 号断点(不禁用编号)
enable 2 # 重新启用
3. 单步执行家族(必背)
n / next # 下一行(不进入函数)
s / step # 单步进入(进入函数)
finish # 执行到当前函数返回
until 行号/地址 # 运行到指定行/地址
c / continue # 继续运行到下一个断点/信号
4. 查看数据(最常用组合)
p / print 变量名 # 最常用
p *array@10 # 打印数组前10个元素
p /x 变量 # 十六进制
p /t 变量 # 二进制
p $rax # 看寄存器(x86_64)
display /i $pc # 每次停下显示当前指令(汇编)
info locals # 当前栈帧局部变量
info args # 当前函数参数
bt / backtrace # 调用栈(崩溃必看)
frame 2 # 切换到第2层栈帧
5. 线程与多线程调试
info threads # 查看所有线程
thread 2 # 切换到 2 号线程
break func thread 3 # 只在 3 号线程的 func 处断点
set scheduler-locking on # 只让当前线程运行(排查死锁神器)
set scheduler-locking off # 恢复多线程调度
6. 核心 dump 分析(线上最重要)
# 1. 产生 core 文件(需先设置)
ulimit -c unlimited
echo "/tmp/core-%e-%p" > /proc/sys/kernel/core_pattern
# 2. 崩溃后分析
gdb ./your_program /tmp/core-your_program-12345
# 然后直接 bt、p、info threads 等
三、生产环境中真正高频的高级技巧
- 远程调试(ssh + gdbserver) 被调试机:
gdbserver :1234 ./your_program arg1 arg2
本地:
gdb ./your_program
(gdb) target remote 被调试机IP:1234
- 条件断点 + 命令列表(自动打印 + 继续)
break func
commands
silent # 不显示停顿提示
print x,y,z
continue
end
- 保存/加载断点
save breakpoints breakpoints.gdb
source breakpoints.gdb
- watch 监视变量变化(神器)
watch global_var
watch *(int*)0x7fffffffdc40 # 监视某个内存地址
- 反汇编 + 寄存器级调试
disas /m main # 带源码的汇编
layout asm # cgdb 里切换到汇编视图
layout split # 源码+汇编同时看
四、快速进阶建议路线(7–14 天)
Day 1–2:熟练 cgdb 界面 + 基本断点/单步/打印
Day 3–4:掌握条件断点、watch、多线程切换
Day 5–6:练习 core dump 分析(自己 kill -6 制造崩溃)
Day 7+:远程调试 + 真实项目跟踪(nginx/redis/mariadb 源码级调试)
你现在最想先解决哪个痛点?
- 界面操作不熟练(cgdb 快捷键记不住)?
- 多线程死锁怎么定位?
- core 文件打不开 / bt 没符号?
- 远程服务器上怎么调试?
- 想看某个具体程序(nginx/redis/mysql)的 gdb 实战案例?
告诉我你的具体场景或卡点,我可以给你针对性的命令序列或调试流程。