常用的GDB调试命令

Evek Golden Lv4

一、常用的 GDB 调试命令

1. 启动调试

  • 启动程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 不带参数
    (gdb) ./program_name # 启动程序进行调试

    # 带参数
    ## 方法1 - 把 MediumBoxBase.conf 作为 argv[1] 传递给 main()
    (gdb) ./MediumBoxBase
    (gdb) set args MediumBoxBase.conf
    (gdb) run

    ## 方法2 - 直接在命令行指定参数,然后在 gdb 里输入 run 启动程序。
    (gdb) --args ./MediumBoxBase MediumBoxBase.conf

    ## 方法3 - 在 shell 里运行 gdb 并传递参数
    (gdb) ./MediumBoxBase
    (gdb) run MediumBoxBase.conf

  • 附加到运行中的进程

    1
    2
    3
    ps aux | grep my_program

    (gdb) -p <pid> # 将 GDB 附加到一个运行中的进程

2. 断点管理

  • 设置断点

    1
    2
    3
    4
    5
    6
    7
    (gdb) break <函数名> 或 b <函数名>    # 在函数入口设置断点
    (gdb) break <文件>:<行号> # 在指定源代码文件和行号设置断点
    (gdb) break <function_name> if <condition> # 在满足条件时设置断点
    (gdb) break <文件>:<函数名> # 在特定文件的函数入口设置断点
    (gdb) break <行号> 或 b <行号> # 在指定行号设置断点
    (gdb) tbreak <行号> # 设置临时断点,触发一次后自动删除

  • 删除断点

    1
    2
    (gdb) delete <breakpoint_number>  # 删除指定断点
    (gdb) delete # 删除所有断点
  • 列出所有断点

    1
    (gdb) info breakpoints 或 i b
  • 启用/禁用断点

    1
    2
    (gdb) enable <breakpoint_number>   # 启用指定断点
    (gdb) disable <breakpoint_number> # 禁用指定断点

3. 程序控制

  • 运行程序

    1
    (gdb) run [args]   # 启动程序,传递参数
  • 暂停程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    (gdb) continue
    # 运行中...
    # 按 Ctrl + C 立即暂停

    # 查看程序当前停在哪
    (gdb) where # 或者 bt (backtrace) # 这会显示调用堆栈,帮助你找出程序在哪个函数、哪一行代码暂停。

    # 查看当前源码
    (gdb) list

    # 查看当前指令
    (gdb) info registers # 查看 CPU 寄存器
    (gdb) disassemble # 反汇编当前代码

  • 继续执行

    1
    (gdb) continue  # 继续执行直到下一个断点
  • 重置程序并从头开始

    1
    2
    3
    4
    5
    6
    7
    # 如果想让程序重新运行,可以使用:
    (gdb) run
    # 但 run 之前,如果程序已经运行过,需要先 kill 掉当前进程:
    (gdb) kill # 终止正在运行的程序
    (gdb) run # 重新运行
    # 如果需要带参数重新运行:
    (gdb) run <参数:MediumBoxBase.conf>
  • 单步调试

    1
    2
    3
    4
    5
    (gdb) step    # 进入当前行代码,进入函数
    (gdb) next # 执行当前行代码,但不会进入函数
    (gdb) finish # 执行直到当前函数结束
    (gdb) until <行号> # 运行到指定行号
    (gdb) jump <行号> # 直接跳转到某一行执行(慎用)
  • 暂停程序

    1
    (gdb) ctrl + C   # 在程序执行时暂停
  • 停止程序

    1
    (gdb) kill  # 停止当前调试进程
  • 重启程序

    1
    (gdb) run  # 重新开始执行程序
  • 在GDB中执行shell

    1
    (gdb) !shell_command
  • 跳转程序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    (gdb) jump <line_number>  # 跳转到指定的代码行
    (gdb) jump <function_name> # 跳转到函数的起始位置
    (gdb) jump <function_name>+<offset> # 跳到函数内某个偏移位置

    # 跳过某段代码 - 用于跳过不重要的代码块,或者在调试时避免进入某些函数
    (gdb) jump main+10 # 跳过 main 函数的前 10 行

    # 限制条件
    (gdb) jump <function_name> if <condition> # 只有在条件满足时才跳转
  • 退出

    1
    (gdb) quit   # 退出 GDB

4. 查看信息

  • 查看调用栈

    1
    2
    3
    (gdb) backtrace   # 查看调用栈
    (gdb) bt # 这是 backtrace 的缩写
    (gdb) backtrace full # 显示完整的调用栈信息,包括局部变量
  • 查看当前的源代码

    1
    2
    (gdb) list   # 显示当前执行行附近的代码
    (gdb) list <line_number> # 显示指定行附近的代码
  • 查看寄存器状态

    1
    (gdb) info registers  # 查看所有寄存器值
  • 查看变量值

1
2
3
4
5
6
7
8
9
(gdb) print <变量名> 或 p <变量名>  # 打印变量的值
(gdb) print x # 打印变量 x 的值
(gdb) print x + y # 打印 x 和 y 相加后的结果
(gdb) print *ptr # 打印指针 ptr 指向的内存内容

(gdb) display <variable_name> # 在每次程序暂停时自动显示变量的值
(gdb) display <变量名> # 在每次执行时自动显示变量值
(gdb) info locals # 查看所有局部变量
(gdb) ptype <变量名> # 显示变量的类型
  • 修改变量值

    1
    2
    #  动态修改程序中的变量值,在某些情况下,修改变量值有助于测试某些边界情况或快速定位问题。
    (gdb) set var <变量名>=<值> # 修改变量值,ex:(gdb) set var x = 10 # 将变量 x 的值设为 10
  • 查看内存

    1
    2
    3
    4
    5
    6
    (gdb) x/<格式> <地址>  # 查看指定地址的内存,<format>可以是x(十六进制),d(十进制)等
    (gdb) x/4xw <地址> # 以 4 个 32 位十六进制格式显示内存
    (gdb) x/10cb <地址> # 以 10 个字节字符格式显示内存
    示例:
    x/10x 0x7fffffffdb60 # 查看 10 个十六进制单元
    x/5i $pc # 查看当前指令
  • 栈帧与函数调用

    1
    2
    3
    4
    (gdb) backtrace 或 bt	#查看调用栈
    (gdb) frame <编号> #切换到指定栈帧
    (gdb) info args #查看当前栈帧的参数
    (gdb) info registers #查看 CPU 寄存器
  • 进程与线程调试

    1
    2
    3
    4
    (gdb) info threads	#查看所有线程
    (gdb) thread <线程ID> #切换到某个线程
    (gdb) break <函数名> thread <线程ID> #在特定线程的函数上设置断点
    (gdb) thread apply all <命令> #在所有线程上执行命令
  • 调试共享库

    1
    2
    3
    (gdb) info sharedlibrary	#显示加载的共享库
    (gdb) set solib-search-path <路径> #指定共享库搜索路径
    (gdb) break <共享库>!<函数> #在动态库函数上设置断点
  • 其他调试技巧

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 调试带动态库的程序
    # 如果程序使用了动态库,运行时可以使用 LD_LIBRARY_PATH 指定库路径:
    LD_LIBRARY_PATH=./libs gdb ./my_program

    # 使用 TUI 模式
    # GDB 提供了 TUI(Text User Interface)模式,可以同时显示代码和调试信息:
    (gdb) layout src # 显示源码
    (gdb) layout asm # 显示汇编
    # 如果界面错乱,可以按 Ctrl + L 刷新。

    # 远程调试
    # 如果要在嵌入式设备或远程服务器上调试程序:
    # 在目标设备上运行:
    (gdb) gdbserver :1234 ./my_program
    # 在本地运行:
    (gdb) my_program
    (gdb) target remote <目标设备IP>:1234

5. 异常处理

  • 当程序崩溃时 如果程序崩溃,gdb 会显示崩溃的位置(通常是调用堆栈)。你可以使用以下命令来查看:

    1
    2
    3
    ulimit -c unlimited  # 允许生成 core dump 文件
    ./your_program # 运行崩溃
    (gdb) ./your_program core # 加载 core 文件分析
    1
    2
    3
    (gdb) backtrace  # 查看调用栈
    (gdb) info locals # 查看当前函数的局部变量
    (gdb) info registers # 查看寄存器内容
  • 调试段错误(Segmentation Fault)

    1. 查找引发崩溃的代码

      1
      (gdb) backtrace   # 查看调用栈,定位崩溃位置
    2. 检查崩溃时的变量

      1
      2
      (gdb) info locals  # 查看当前函数的局部变量
      (gdb) print <variable_name> # 打印崩溃时的变量值
  • 调试死循环 当程序进入死循环时,首先暂停程序执行,然后使用以下命令来定位问题:

    1
    2
    (gdb) backtrace   # 查看调用栈
    (gdb) info locals # 查看变量状态

二、异常处理的操作实践

1. 使用断点定位问题

  • 设置断点在关键函数或怀疑的代码区域进行检查:

    1
    2
    (gdb) break <function_name>
    (gdb) break <file>:<line_number>

2. 使用条件断点

  • 为了排除不相关的调试情况,可以设置带条件的断点,只有满足某些条件时才中断:

    1
    (gdb) break <function_name> if <condition>

3. 检查内存问题

  • 使用

    1
    valgrind

    等工具检查内存问题后,通过

    1
    gdb

    分析崩溃位置:

    1
    2
    3
    (gdb) backtrace   # 查看调用栈
    (gdb) info locals # 检查局部变量
    (gdb) print <variable> # 打印变量值,特别是指针

4. 运行时的状态检查

  • 在程序运行时,如果怀疑某个变量的值不对,可以使用

    1
    watch

    命令监控变量:

    1
    2
    3
    4
    5
    6
    7
    8
    (gdb) watch <variable_name>   # 监视某个变量的变化
    (gdb) watch <expression> # 监视表达式的变化
    (gdb) watch i if i > 10 # 当 i > 10 时中断

    (gdb) delete watch # 删除所有 watch 点
    (gdb) delete <watch_point_number> # 删除指定的 watch 点

    (gdb) watch *ptr # 监视指针 ptr 指向的内存内容变化

5. 捕获异常

  • 如果程序在某些点抛出异常(比如 C++ 中的

    1
    throw

    可以在抛出点设置断点:

    1
    2
    (gdb) catch throw  # 捕获抛出的异常
    (gdb) catch catch # 捕获异常处理的地方

三、调试常见问题

  1. 程序崩溃时,无法定位原因
    • 使用 gdb 获取崩溃位置(backtrace),然后检查相关的局部变量和堆栈状态,查找不合适的指针或内存访问。
  2. 程序死循环
    • 使用 gdb 查看程序的调用栈(backtrace),找出可能重复调用的函数。通过单步调试(stepnext)排查死循环逻辑。
  3. 无法连接到进程
    • 确保以正确权限运行 gdb,并且进程 ID 是正确的。如果是目标程序没有启动,可以尝试通过 gdb 启动程序。
  • Title: 常用的GDB调试命令
  • Author: Evek Golden
  • Created at : 2025-08-21 15:19:00
  • Updated at : 2026-06-12 08:57:02
  • Link: https://blog.cocodemo.uno/posts/4cf628f1/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments