GDB(GNU Debugger) GNU 命令行调试器 调试 C、C++、Go、Rust、Ada 等多种编程语言编写的程序

GDB(GNU Debugger)是 GNU 项目开发的一款强大且通用的命令行调试器 ,主要用于调试 C、C++、Go、Rust、Ada 等多种编程语言编写的程序。它是 Linux 和类 Unix 系统下最常用、最核心的调试工具

简单来说,GDB 能让你像"侦探"一样深入程序内部,观察、控制和分析它的运行状态,从而高效地定位和修复 Bug(尤其是崩溃和逻辑错误)。

🧠 GDB 的核心功能

GDB 的能力主要围绕以下四个方面展开:

功能 说明 常用命令/操作
🚀 启动与控制程序 按你的要求运行程序,随时暂停、继续、或单步执行。 run ®, continue ©, next (n), step (s), finish
🔴 设置断点 在代码的指定行、函数入口或条件表达式处暂停程序。 break (b), break <行号>, break <函数名>, break <行号> if <条件>
🔍 检查程序状态 当程序暂停时,查看变量、内存、寄存器、调用栈等内部状态。 print §, backtrace (bt), info locals, info args, x
🛠️ 动态修改环境 在调试过程中修改变量值、调用函数,甚至改变执行顺序,测试不同修复方案。 set var <变量>=<值>, call <函数()>, jump <地址>

📦 如何使用 GDB 调试程序

使用 GDB 调试程序通常需要遵循以下步骤,其核心流程可概括如下:
#mermaid-svg-dW2o2g1vSQTupjNb{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dW2o2g1vSQTupjNb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dW2o2g1vSQTupjNb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dW2o2g1vSQTupjNb .error-icon{fill:#552222;}#mermaid-svg-dW2o2g1vSQTupjNb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dW2o2g1vSQTupjNb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dW2o2g1vSQTupjNb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dW2o2g1vSQTupjNb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dW2o2g1vSQTupjNb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dW2o2g1vSQTupjNb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dW2o2g1vSQTupjNb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dW2o2g1vSQTupjNb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dW2o2g1vSQTupjNb .marker.cross{stroke:#333333;}#mermaid-svg-dW2o2g1vSQTupjNb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dW2o2g1vSQTupjNb p{margin:0;}#mermaid-svg-dW2o2g1vSQTupjNb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dW2o2g1vSQTupjNb .cluster-label text{fill:#333;}#mermaid-svg-dW2o2g1vSQTupjNb .cluster-label span{color:#333;}#mermaid-svg-dW2o2g1vSQTupjNb .cluster-label span p{background-color:transparent;}#mermaid-svg-dW2o2g1vSQTupjNb .label text,#mermaid-svg-dW2o2g1vSQTupjNb span{fill:#333;color:#333;}#mermaid-svg-dW2o2g1vSQTupjNb .node rect,#mermaid-svg-dW2o2g1vSQTupjNb .node circle,#mermaid-svg-dW2o2g1vSQTupjNb .node ellipse,#mermaid-svg-dW2o2g1vSQTupjNb .node polygon,#mermaid-svg-dW2o2g1vSQTupjNb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dW2o2g1vSQTupjNb .rough-node .label text,#mermaid-svg-dW2o2g1vSQTupjNb .node .label text,#mermaid-svg-dW2o2g1vSQTupjNb .image-shape .label,#mermaid-svg-dW2o2g1vSQTupjNb .icon-shape .label{text-anchor:middle;}#mermaid-svg-dW2o2g1vSQTupjNb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dW2o2g1vSQTupjNb .rough-node .label,#mermaid-svg-dW2o2g1vSQTupjNb .node .label,#mermaid-svg-dW2o2g1vSQTupjNb .image-shape .label,#mermaid-svg-dW2o2g1vSQTupjNb .icon-shape .label{text-align:center;}#mermaid-svg-dW2o2g1vSQTupjNb .node.clickable{cursor:pointer;}#mermaid-svg-dW2o2g1vSQTupjNb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dW2o2g1vSQTupjNb .arrowheadPath{fill:#333333;}#mermaid-svg-dW2o2g1vSQTupjNb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dW2o2g1vSQTupjNb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dW2o2g1vSQTupjNb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dW2o2g1vSQTupjNb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dW2o2g1vSQTupjNb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dW2o2g1vSQTupjNb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dW2o2g1vSQTupjNb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dW2o2g1vSQTupjNb .cluster text{fill:#333;}#mermaid-svg-dW2o2g1vSQTupjNb .cluster span{color:#333;}#mermaid-svg-dW2o2g1vSQTupjNb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dW2o2g1vSQTupjNb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dW2o2g1vSQTupjNb rect.text{fill:none;stroke-width:0;}#mermaid-svg-dW2o2g1vSQTupjNb .icon-shape,#mermaid-svg-dW2o2g1vSQTupjNb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dW2o2g1vSQTupjNb .icon-shape p,#mermaid-svg-dW2o2g1vSQTupjNb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dW2o2g1vSQTupjNb .icon-shape .label rect,#mermaid-svg-dW2o2g1vSQTupjNb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dW2o2g1vSQTupjNb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dW2o2g1vSQTupjNb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dW2o2g1vSQTupjNb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是



编译程序

加入-g选项
启动GDB

gdb ./程序名
设置断点

break 行号/函数名
运行程序

run
程序是否在断点处暂停?
检查程序状态

print变量/backtrace调用栈
单步执行或继续

next/step/continue
是否发现Bug?
修复代码
继续调试至结束
程序运行结束

或崩溃
分析崩溃信息

或正常退出

1. 编译程序时加入调试信息

这是使用 GDB 的前提 。必须使用 gccg++ 编译时加上 -g 选项,才能生成包含调试符号(变量名、行号等)的可执行文件。

bash 复制代码
# 示例:编译 test.cpp 生成带调试信息的可执行程序 test
g++ -g test.cpp -o test
2. 启动 GDB 并加载程序

在终端中输入 gdb 加上你的可执行程序路径即可启动。

bash 复制代码
gdb ./test

也可以直接在 GDB 中使用 file 命令加载程序:

gdb 复制代码
(gdb) file ./test
3. 设置断点

使用 break 命令(简写为 b)设置断点,程序运行到此处会暂停。

gdb 复制代码
(gdb) break main        # 在 main 函数入口处设置断点
(gdb) b 15              # 在第 15 行设置断点
(gdb) b my_function     # 在 my_function 函数入口设置断点
4. 运行程序

使用 run 命令(简写为 r)启动程序。程序会一直运行直到遇到断点。

gdb 复制代码
(gdb) run

如果程序需要参数,可以在 run 后面直接跟上参数:

gdb 复制代码
(gdb) run arg1 arg2
5. 检查程序状态

程序暂停后,你可以使用各种命令检查其状态:

  • 查看变量值print (简写为 p)

    gdb 复制代码
    (gdb) print sum
    $1 = 10
    (gdb) p *array@10     # 查看数组array前10个元素
  • 查看调用栈backtrace (简写为 bt),了解函数调用关系

    gdb 复制代码
    (gdb) backtrace
    #0  main () at test.cpp:15
  • 查看局部变量info locals

  • 查看内存内容x 命令

6. 控制程序执行
  • 单步执行(不进入函数)next (简写为 n)
  • 单步执行(进入函数)step (简写为 s)
  • 继续运行到下一个断点continue (简写为 c)
  • 执行完当前函数finish
7. 修改变量并测试

可以在调试过程中修改变量的值,以测试不同的执行路径或修复方案。

gdb 复制代码
(gdb) set var i = 5      # 将变量 i 的值修改为 5

🐛 使用 GDB 分析程序崩溃(如段错误)

当程序崩溃(如出现 Segmentation fault)时,GDB 是事后分析的利器。

  1. 直接调试崩溃程序 :用 GDB 运行程序,当其崩溃时,GDB 会自动捕获并暂停。此时使用 bt 命令查看崩溃时的调用栈 ,能立即定位到出问题的函数和行号。

    gdb 复制代码
    (gdb) run
    Program received signal SIGSEGV, Segmentation fault.
    0x0000555555555170 in main () at test.cpp:15
    15	        *p = 100;      // 崩溃在这一行
    (gdb) bt
    #0  0x0000555555555170 in main () at test.cpp:15
  2. 分析 Core Dump 文件 :如果系统生成了 core dump 文件(通常在崩溃时自动生成),可以用 GDB 加载它来复盘崩溃现场。

    bash 复制代码
    gdb ./test core       # 加载可执行程序和 core 文件
    (gdb) bt              # 查看崩溃时的调用栈

💡 GDB 使用技巧与进阶

  • 查看源代码list (简写为 l) 命令可以查看源代码。

    gdb 复制代码
    (gdb) list           # 查看当前位置附近的代码
    (gdb) list 15        # 查看第15行附近的代码
    (gdb) list main      # 查看 main 函数的代码
  • 观察点(Watchpoint)watch 命令可以设置观察点,当某个表达式的值发生变化时程序暂停,非常适合追踪变量被意外修改的情况。

  • 条件断点 :设置断点时可以附加条件,只有条件满足才暂停,极大提高调试效率。

    gdb 复制代码
    (gdb) break 10 if i == 5    # 当 i 等于 5 时,在第10行暂停
  • 使用 .gdbinit 文件 :可以在用户主目录下创建 .gdbinit 文件,写入常用的 GDB 命令,GDB 启动时会自动执行,避免重复输入。

  • 图形化前端 :如果觉得纯命令行不便,可以使用基于 GDB 的图形化或文本前端工具,如 cgdb(分屏显示源码和命令)、DDD 等。

⚠️ 注意事项

  1. 务必使用 -g 编译 :忘记加 -g 选项会导致 GDB 无法显示源代码行号和变量名,几乎无法调试。
  2. 优化与调试信息 :在编译时使用 -O 优化选项(如 -O2)可能会打乱代码顺序,使调试变得困难。调试时建议关闭优化或使用 -Og(优化调试体验)。
  3. GDB 与 IDE 调试器:VS Code、CLion 等 IDE 的调试功能底层通常也是调用 GDB 或 LLDB,它们提供了更友好的图形界面。

📚 总结与学习资源

GDB 是 Linux 环境下 C/C++ 开发者必备的核心技能。它虽然基于命令行,但功能强大,灵活性远超许多图形化调试器。

💡 学习建议 :从最基础的 runbreaknextprintbacktrace 命令练起,结合实际调试一个小程序,很快就能上手。遇到具体问题再查阅手册学习新命令。

  • 官方手册info gdb 或在线手册 GDB Documentation 是最权威的参考。
  • 实践练习:多写几个有 Bug 的小程序(如数组越界、空指针解引用、死循环),用 GDB 去定位和修复它们,这是最快的掌握方式。
  • 推荐教程
    • 《GDB Pocket Reference》
    • 许多优秀的 Linux C/C++ 开发书籍都有专门的 GDB 章节。
      掌握 GDB,你就能从"程序能跑通"进化到"程序为什么能跑通/跑崩",真正理解程序的内部世界。