标签: gdb

  • GDB调试小技巧

    GDB(GNU Debugger)是调试 C/C++ 等程序的强大工具,掌握一些高效技巧能大幅提升调试效率。以下是一些实用技巧:

    一、基础调试命令

    1. 启动调试
      gdb ./program # 调试可执行文件
      gdb -p <pid> # 附加到正在运行的进程
    2. 设置断点
      break main # 在 main 函数设置断点
      break file.c:20 # 在 file.c 的第 20 行设置断点
      break func # 在函数 func 处设置断点
      info breakpoints # 查看所有断点
      delete <num> # 删除断点(num 为断点编号)
    3. 运行与控制
      run <args> # 启动程序并传入参数
      continue # 继续运行到下一个断点
      next (n) # 单步执行(不进入函数)
      step (s) # 单步执行(进入函数)
      finish # 执行完当前函数并返回

    二、查看变量与内存

    1. 打印变量
      print var # 打印变量值
      print *ptr@10 # 打印指针 ptr 指向的 10 个元素
      print/x var # 以十六进制格式打印变量
    2. 自动显示变量
      display var # 每次断点后自动显示变量值
      undisplay <num> # 取消自动显示
    3. 检查内存
      x/s addr # 检查 addr 处的字符串
      # 格式说明:x/[数量][格式][单位]
      # 单位:b(byte), h(half-word), w(word), g(giant word)

      # 以十六进制检查 addr 处的10个字(4字节)
      x/10xw addr

    三、高级调试技巧

    1. 条件断点
      break file.c:20 if i == 5 # 当 i=5 时触发断点
      condition <num> i > 10 # 修改已有断点的条件
    2. 观察点(Watchpoint)
      watch var # 当变量被修改时暂停
      rwatch var # 当变量被读取时暂停
      awatch var # 变量被读写时均暂停
    3. 捕获事件
      catch throw # 捕获 C++ 异常
      catch syscall open # 捕获系统调用(如 open)
    4. 修改运行时的值
      set variable i = 10 # 修改变量 i 的值
      call func() # 强制调用函数
      return 0 # 强制从当前函数返回

    四、堆栈与多线程

    1. 查看堆栈
      backtrace (bt) # 显示调用堆栈
      frame <num> # 切换到指定堆栈帧
      info locals # 查看当前栈帧的局部变量
    2. 多线程调试
      info threads # 查看所有线程
      thread <num> # 切换到指定线程
      break func thread 2 # 在线程 2 的 func 处设置断点

    五、信号处理

    handle SIGSEGV nostop   # 收到 SIGSEGV 时不暂停
    handle SIGINT print # 打印 SIGINT 信号信息

    六、其他实用功能

    1. TUI 模式
      gdb -tui ./program # 启动文本界面(显示代码窗口)
      Ctrl+X+A # 在普通模式和 TUI 模式间切换
    2. 记录执行过程
      record # 开始记录执行过程(反向调试)
      reverse-step # 反向执行(需先执行 record)
    3. 调试崩溃后的 core 文件
      gdb ./program core # 分析崩溃的 core dump 文件

    七、调试脚本

    将常用命令写入 .gdbinit 文件,或通过 source 命令加载脚本:

    gdb -x script.gdb ./program  # 执行 script.gdb 中的命令

    八、常见问题解决

    • 编译时添加调试信息:确保编译时加上 -g 选项(如 gcc -g -o program program.c)。
    • 找不到源码:使用 directory /path/to/source 指定源码路径。
    • 查看寄存器info registersprint $rax