3. gdb调试.md 8.8 KB


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 选项生成调试信息:

# 基本用法
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 直接启动

# 启动并加载程序
gdb ./program

# 启动后加载已有程序
gdb
(gdb) file ./program

3.2 带参数启动

# 使用 --args 传递命令行参数
gdb --args ./program arg1 arg2

# 或在gdb内使用 set args
gdb ./program
(gdb) set args arg1 arg2

3.3 调试core dump

gdb ./program core

4. 常用命令

4.1 运行控制

命令 简写 说明
run r 运行程序(可带参数)
start - 运行到main函数暂停
continue c 继续运行,直到下一个断点
kill k 终止当前程序
quit q 退出gdb
(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 断点号 启用断点
# 在第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 行号 执行到指定行
(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行)
(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)

# 当变量值变化时中断
(gdb) watch variable

# 当变量被读取时中断
(gdb) rwatch variable

# 当变量被读或写时中断
(gdb) awatch variable

# 查看观察点
(gdb) info watchpoints

5. 多线程调试

# 查看所有线程
(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

# 查看当前限制
ulimit -c

# 开启core dump(无大小限制)
ulimit -c unlimited

# 设置core文件名格式(可选)
echo "/tmp/core.%e.%p" > /proc/sys/kernel/core_pattern

6.2 分析core dump

# 使用gdb分析
gdb ./program core

# 或使用coredumpctl(systemd系统)
coredumpctl list
coredumpctl gdb PID

6.3 常用core dump分析命令

(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 目标板配置

# 目标板启动gdbserver
gdbserver :1234 ./program
# 或使用串口
gdbserver /dev/ttyS0 ./program

7.3 主机端连接

# 启动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 交叉编译调试

# 交叉编译带调试信息
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模式(图形界面)

# 启动TUI模式
gdb -tui ./program

# 在gdb内切换
(gdb) layout src    # 显示源代码窗口
(gdb) layout asm    # 显示汇编窗口
(gdb) layout regs   # 显示寄存器
(gdb) focus cmd     # 切换焦点到命令窗口

8.2 调试宏

# 查看宏定义
(gdb) macro expand MACRO_NAME

# 查看所有宏
(gdb) info macros

8.3 条件断点高级用法

# 忽略前N次命中
(gdb) ignore 1 10  # 断点1忽略前10次

# 命中断点时执行命令
(gdb) commands 1
> print variable
> continue
> end

8.4 调试优化代码

# 如果必须调试优化代码
gcc -g -O1 -o program program.c

# gdb中查看优化掉的变量
(gdb) info optimization

8.5 常用组合技

# 打印数组所有元素
(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. 条件断点的作用?

    • 减少中断次数,只在特定条件下暂停,提高调试效率

常见命令速查

# 崩溃分析三板斧
gdb ./program core
(gdb) bt
(gdb) print variable
(gdb) info registers

# 悬空指针调试
(gdb) watch *ptr
(gdb) continue

# 查看系统调用
(gdb) catch syscall

本文件用于知识归档,内容可直接用于学习与复习。