调试器---GDB(Linux/Unix平台下编译型语言,C++、Go、Rust)

GDB 是C++后端开发、底层调试的核心武器

一、GDB 是什么?

GDB 全称 GNU Debugger ,是Linux/Unix平台下免费、开源、功能最强的程序调试器,完美支持 C/C++、Go、Rust 等编译型语言。

它的核心能力:

  1. 控制程序的启动/暂停/单步执行
  2. 查看程序运行时的变量、内存、调用栈
  3. 断点调试、条件触发、内存观察
  4. 定位崩溃(段错误)、死锁、逻辑错误
  5. 调试运行中的进程、core转储文件(线上排查必备)

二、前置准备:编译带调试信息的程序

GDB 无法调试纯发行版程序,编译时必须添加调试符号!

基础编译命令(C++)

bash 复制代码
# -g:生成标准调试信息
# -O0:关闭编译器优化(优化会打乱代码执行顺序,导致调试异常)
g++ -g -O0 main.cpp -o my_program

进阶推荐

bash 复制代码
# -ggdb:生成GDB专属调试信息,功能更全
g++ -ggdb -O0 main.cpp -o my_program

⚠️ 避坑:生产环境可以关闭调试符号,但测试/调试环境必须加 -g 且禁止优化


三、GDB 三种启动方式

1. 直接调试可执行文件

bash 复制代码
gdb ./my_program

启动后进入 GDB 交互模式,提示符:(gdb)

2. 调试崩溃后的 core 文件(线上崩溃排查)

程序崩溃后会生成 core.xxx 文件,直接复盘崩溃现场:

bash 复制代码
# 先开启core文件生成(执行一次即可)
ulimit -c unlimited

# 调试core文件
gdb ./my_program core.12345

3. 附加到运行中的进程(调试在线服务)

程序已经在运行,无需重启,直接附加调试:

bash 复制代码
# 先查进程PID
ps -ef | grep my_program

# 附加到进程
gdb -p 12345

四、GDB 基础核心命令

用一个简单的C++示例程序演示:

cpp 复制代码
// main.cpp
#include <iostream>
#include <vector>
using namespace std;

int add(int a, int b) {
    return a + b;
}

int main() {
    int x = 10, y = 20;
    int res = add(x, y);
    cout << res << endl;

    vector<int> vec = {1,2,3};
    return 0;
}

1. 程序控制命令

命令 简写 作用
run r 启动程序(从头运行)
start - 启动程序,暂停在main函数第一行
continue c 继续运行程序,直到下一个断点/崩溃
next n 单步执行(不进入函数内部,逐行跑)
step s 单步执行(进入函数内部,比如进入add函数)
quit q 退出GDB

2. 断点管理(调试的核心)

断点让程序在指定位置暂停,方便排查问题:

gdb 复制代码
# 1. 在指定行打断点
break 10       # b 10 → 暂停在第10行
break main     # b main → 暂停在main函数入口
break add      # 暂停在add函数入口

# 2. 条件断点(进阶)
break 10 if x==10  # 只有x=10时才触发断点

# 3. 查看所有断点
info breakpoints  # i b

# 4. 删除断点
delete 1    # 删除编号为1的断点
delete      # 删除所有断点

3. 查看代码上下文

gdb 复制代码
list          # l → 显示当前行前后10行代码
list 1,20     # 显示1-20行代码
list add      # 显示add函数的代码

4. 查看变量/内存(排查数值错误)

gdb 复制代码
# 打印变量
print x       # p x → 打印变量x的值
print res     # 打印计算结果

# 打印C++对象/容器
print vec     # 打印vector对象
print vec[0]  # 打印容器元素

# 格式化打印
print /x x    # 以十六进制打印
print /d x    # 以十进制打印

# 修改变量值(调试神器)
set var x=100 # 把x的值改成100,测试逻辑

5. 栈回溯(定位崩溃/调用链)

这是定位段错误的第一命令

gdb 复制代码
bt            # 查看函数调用栈(崩溃时看哪一行出错)
bt full       # 查看完整调用栈 + 所有局部变量(最强)
frame 0       # 切换到指定栈帧

五、实战:C++ 段错误(Segmentation fault)排查

段错误是C++最常见的崩溃(空指针、野指针、数组越界),我们用GDB快速定位:

测试代码(故意制造空指针)

cpp 复制代码
#include <iostream>
using namespace std;

void test() {
    int* p = nullptr; // 空指针
    *p = 10; // 非法访问内存 → 段错误
}

int main() {
    test();
    return 0;
}

调试流程

  1. 编译:g++ -g -O0 main.cpp -o crash
  2. 启动GDB:gdb ./crash
  3. 运行程序:(gdb) run
  4. 程序崩溃,执行:(gdb) bt full
  5. 查看崩溃代码:(gdb) list
  6. 查看可疑指针:(gdb) print p

输出结果 :直接看到p = 0x0(空指针),崩溃行一目了然。


六、C++ 专属调试技巧

GDB 对C++的类、对象、虚函数、STL、多线程有专属支持,这是区别于C语言调试的关键:

1. 调试C++ 类与对象

cpp 复制代码
class Test {
public:
    int num = 0;
    void func() { num = 100; }
};
gdb 复制代码
# 打印对象成员变量
print test_obj.num

# 调用对象成员函数
print test_obj.func()

# 调试虚函数
print *virtual_ptr # 查看虚表指针

2. 调试 STL 容器(vector/map/string)

默认GDB打印STL会很冗长,推荐直接访问元素:

gdb 复制代码
print vec.size()
print vec[0]
print map["key"]
print str.c_str()

3. 多线程调试

gdb 复制代码
info threads       # 查看所有线程
thread 2           # 切换到2号线程
break 10 thread 2  # 仅在2号线程第10行打断点

4. 观察点(监控内存修改)

排查内存被意外篡改的神器:

gdb 复制代码
watch p    # 当指针p的值改变时,程序自动暂停
rwatch p   # 当读取p时暂停
awatch p   # 读写p时都暂停

七、GDB 高级实用技巧

1. 日志输出

把调试信息保存到文件,方便复盘:

gdb 复制代码
set logging file gdb.log
set logging on

2. 跳过代码执行

调试时跳过某行错误代码,无需改源码:

gdb 复制代码
jump 15  # 直接跳转到第15行执行

3. 查看内存原始数据

gdb 复制代码
x/10i main  # 查看main函数的汇编代码
x/10w p     # 查看指针p指向的10个内存值

八、注意避坑

  1. 忘记加 -g 编译:GDB 看不到源码和变量,直接报废
  2. 开启编译器优化-O2 会打乱代码行,单步执行异常
  3. 混淆 next 和 stepn 不进函数,s 进函数,别用错

总结

对于C++来说,GDB 不是可选工具,而是必备技能

  1. 基础:run/break/next/print/bt 搞定大多数的调试场景
  2. 进阶:core文件、多线程、观察点,搞定线上崩溃
  3. C++专属:类、STL、虚函数调试,贴合实际开发

抛弃低效的cout/printf调试,熟练使用GDB后,排查bug的效率会提升10倍以上。

相关推荐
头发够用的程序员1 小时前
WSL2 Ubuntu 24.04 离线安装 Docker 全流程
linux·ubuntu·docker
xingfujie1 小时前
第1章:整体架构与准备工作
linux·云原生·容器·架构·kubernetes·kubelet
jsons11 小时前
linux 用户内存保障管理配置
linux·运维·服务器
宏笋1 小时前
C++ string 和string_view的区别和用法
c++
宏笋1 小时前
C++ 回调函数详解和常用场景
开发语言·c++
WBluuue1 小时前
Codeforces 1095 Div2(ABCDE)
c++·算法
用户2367829801681 小时前
Linux top 命令深度解析:进程监控的性能优化实战
linux
web守墓人1 小时前
【AI编程】小米mimo模型400错误处理,以及roocode修复指南
linux·ubuntu·ai编程
xingfujie1 小时前
前言:从零到一,系统掌握 K8s + DevOps + 微服务
linux·运维·微服务·云原生·容器·kubernetes·devops