--- title: gdb调试 type: raw created: 2026-08-31 tags: [debugging, gdb, linux, c-cpp] --- # gdb调试 ## 1. gdb是什么 gdb(GNU Debugger)是GNU项目中的标准调试器,是Linux/Unix系统下C/C++程序调试的核心工具。它是一个命令行调试工具,支持: - 断点设置与管理 - 单步执行(逐行/逐函数) - 变量/内存查看 - 调用栈回溯 - 多线程调试 - 核心转储(core dump)分析 - 远程调试 ## 2. 编译选项 使用gcc/g++编译时必须添加 `-g` 选项生成调试信息: ```bash # 基本用法 gcc -g -o program program.c # 优化编译(调试时建议关闭优化) gcc -g -O0 -o program program.c # C++编译 g++ -g -o program program.cpp ``` **注意**:调试时建议使用 `-O0` 禁用优化,否则变量可能被优化掉,无法正常调试。 ## 3. 启动gdb ### 3.1 直接启动 ```bash # 启动并加载程序 gdb ./program # 启动后加载已有程序 gdb (gdb) file ./program ``` ### 3.2 带参数启动 ```bash # 使用 --args 传递命令行参数 gdb --args ./program arg1 arg2 # 或在gdb内使用 set args gdb ./program (gdb) set args arg1 arg2 ``` ### 3.3 调试core dump ```bash gdb ./program core ``` ## 4. 常用命令 ### 4.1 运行控制 | 命令 | 简写 | 说明 | | ---------- | ---- | ------------------------ | | `run` | `r` | 运行程序(可带参数) | | `start` | - | 运行到main函数暂停 | | `continue` | `c` | 继续运行,直到下一个断点 | | `kill` | `k` | 终止当前程序 | | `quit` | `q` | 退出gdb | ```bash (gdb) run (gdb) run arg1 arg2 (gdb) start (gdb) continue ``` ### 4.2 断点管理 | 命令 | 简写 | 说明 | | ------------------- | ------------- | -------------------- | | `break 行号` | `b 行号` | 在指定行设断点 | | `break 函数名` | `b 函数名` | 在函数入口设断点 | | `break 文件:行号` | `b 文件:行号` | 在指定文件的行设断点 | | `break ... if 条件` | - | 条件断点 | | `info breakpoints` | `i b` | 查看所有断点 | | `delete 断点号` | `d 断点号` | 删除断点 | | `disable 断点号` | `dis 断点号` | 禁用断点 | | `enable 断点号` | `en 断点号` | 启用断点 | ```bash # 在第10行设断点 (gdb) break 10 # 在函数main设断点 (gdb) break main # 条件断点:当i==5时中断 (gdb) break 15 if i==5 # 查看断点 (gdb) info breakpoints ``` ### 4.3 单步执行 | 命令 | 简写 | 说明 | | ------------ | -------- | ------------------------ | | `next` | `n` | 单步执行,不进入函数内部 | | `step` | `s` | 单步执行,进入函数内部 | | `finish` | `fin` | 执行到当前函数返回 | | `until 行号` | `u 行号` | 执行到指定行 | ```bash (gdb) next # 执行下一行,跳过函数 (gdb) step # 执行下一行,进入函数 (gdb) finish # 执行到当前函数返回 (gdb) until 20 # 执行到第20行 ``` ### 4.4 查看信息 | 命令 | 简写 | 说明 | | ---------------- | ---------- | ---------------------------- | | `print 表达式` | `p 表达式` | 打印变量/表达式值 | | `print *指针` | `p *指针` | 打印指针指向的内容 | | `display 表达式` | - | 每次暂停时自动打印 | | `info locals` | `i locals` | 查看所有局部变量 | | `info args` | `i args` | 查看函数参数 | | `backtrace` | `bt` | 查看调用栈 | | `backtrace full` | `bt full` | 查看调用栈及局部变量 | | `list` | `l` | 查看源代码(当前行前后10行) | ```bash (gdb) print variable (gdb) print *ptr (gdb) print arr[0] (gdb) print sizeof(arr) (gdb) backtrace # #0 func1 () at test.c:10 # #1 0x0000555555555149 in main () at test.c:20 (gdb) info locals (gdb) list 5,15 # 显示第5-15行 ``` ### 4.5 观察点(Watchpoint) ```bash # 当变量值变化时中断 (gdb) watch variable # 当变量被读取时中断 (gdb) rwatch variable # 当变量被读或写时中断 (gdb) awatch variable # 查看观察点 (gdb) info watchpoints ``` ## 5. 多线程调试 ```bash # 查看所有线程 (gdb) info threads # Id Target Id Frame # * 1 Thread 0x7ffff... main () at test.c:10 # 2 Thread 0x7fff8... 0x00007ffff... in pthread_join () # 切换到指定线程 (gdb) thread 2 # 为所有线程设断点 (gdb) thread apply all bt # 在特定线程执行命令 (gdb) thread apply 1-3 print variable ``` ## 6. Core Dump分析 ### 6.1 开启core dump ```bash # 查看当前限制 ulimit -c # 开启core dump(无大小限制) ulimit -c unlimited # 设置core文件名格式(可选) echo "/tmp/core.%e.%p" > /proc/sys/kernel/core_pattern ``` ### 6.2 分析core dump ```bash # 使用gdb分析 gdb ./program core # 或使用coredumpctl(systemd系统) coredumpctl list coredumpctl gdb PID ``` ### 6.3 常用core dump分析命令 ```bash (gdb) bt # 查看崩溃时调用栈 (gdb) bt full # 包含局部变量 (gdb) info registers # 查看寄存器 (gdb) frame N # 切换到第N层栈帧 (gdb) print variable # 查看变量值 ``` ## 7. 嵌入式远程调试 ### 7.1 gdb + gdbserver架构 ``` Host (开发机) Target (目标板) +-----------+ +-----------+ | gdb | <--- TCP/串口 ---> | gdbserver | +-----------+ +-----------+ | program ``` ### 7.2 目标板配置 ```bash # 目标板启动gdbserver gdbserver :1234 ./program # 或使用串口 gdbserver /dev/ttyS0 ./program ``` ### 7.3 主机端连接 ```bash # 启动gdb gdb ./program # 连接目标板 (gdb) target remote 192.168.1.100:1234 # 或串口 (gdb) target remote /dev/ttyUSB0 # 然后正常调试 (gdb) break main (gdb) run (gdb) continue ``` ### 7.4 交叉编译调试 ```bash # 交叉编译带调试信息 arm-linux-gnueabihf-gcc -g -o program program.c # 使用交叉gdb arm-linux-gnueabihf-gdb ./program (gdb) target remote 192.168.1.100:1234 ``` ## 8. 实用技巧 ### 8.1 TUI模式(图形界面) ```bash # 启动TUI模式 gdb -tui ./program # 在gdb内切换 (gdb) layout src # 显示源代码窗口 (gdb) layout asm # 显示汇编窗口 (gdb) layout regs # 显示寄存器 (gdb) focus cmd # 切换焦点到命令窗口 ``` ### 8.2 调试宏 ```bash # 查看宏定义 (gdb) macro expand MACRO_NAME # 查看所有宏 (gdb) info macros ``` ### 8.3 条件断点高级用法 ```bash # 忽略前N次命中 (gdb) ignore 1 10 # 断点1忽略前10次 # 命中断点时执行命令 (gdb) commands 1 > print variable > continue > end ``` ### 8.4 调试优化代码 ```bash # 如果必须调试优化代码 gcc -g -O1 -o program program.c # gdb中查看优化掉的变量 (gdb) info optimization ``` ### 8.5 常用组合技 ```bash # 打印数组所有元素 (gdb) p arr@10 # 打印arr[0]到arr[9] # 修改变量值 (gdb) set variable = 100 # 调用函数 (gdb) call func(arg) # 显示内存 (gdb) x/20xw 0x7fffffffe000 # 显示20个4字节十六进制值 ``` ## 9. 注意事项 1. **编译选项**:必须使用 `-g` 编译,否则无法单步调试 2. **优化影响**:`-O2`/`-O3` 优化会导致代码顺序变化,调试困难 3. **权限问题**:gdb调试自身进程不需要root,调试其他进程需要 4. **安全限制**:系统可能限制ptrace,需关闭`YAMA`或具有CAP_SYS_PTRACE 5. **core文件大小**:注意ulimit设置,可能限制core文件生成 6. **符号表**:strip后的程序无法调试,需保留符号表 ## 10. 面试要点 ### 高频问题 1. **gdb如何调试段错误?** - 开启core dump,分析backtrace定位崩溃位置 2. **如何调试多线程程序?** - `info threads`查看线程,`thread N`切换,`thread apply`批量操作 3. **如何调试内存泄漏?** - 使用valgrind或AddressSanitizer,gdb中通过watchpoint追踪 4. **gdb和Valgrind的区别?** - gdb是运行时调试,可交互式;Valgrind是运行时检测,报告问题 5. **如何调试release版本?** - 保留debug符号(`-g`),或使用addr2line将地址转为源码行号 6. **条件断点的作用?** - 减少中断次数,只在特定条件下暂停,提高调试效率 ### 常见命令速查 ```bash # 崩溃分析三板斧 gdb ./program core (gdb) bt (gdb) print variable (gdb) info registers # 悬空指针调试 (gdb) watch *ptr (gdb) continue # 查看系统调用 (gdb) catch syscall ``` --- _本文件用于知识归档,内容可直接用于学习与复习。_