GDB 调试与 Core Dump(段错误)排查指南(Linux/C/C++)

GDB 调试与 Core Dump(段错误)排查指南(Linux/C/C++)

目录(大纲)

  • [1. GDB 是什么?能解决什么问题?](#1. GDB 是什么?能解决什么问题?)
  • [2. 编译准备:一定要带调试信息](#2. 编译准备:一定要带调试信息)
  • [3. GDB 常用命令速查(高频)](#3. GDB 常用命令速查(高频))
  • [4. 实战:用 GDB 定位段错误(SIGSEGV)](#4. 实战:用 GDB 定位段错误(SIGSEGV))
  • [5. Core Dump:程序崩了也能"回放现场"](#5. Core Dump:程序崩了也能“回放现场”)
  • [6. 段错误(Segmentation fault)常见原因总结](#6. 段错误(Segmentation fault)常见原因总结)
  • [7. 高效排查套路(建议你照着做)](#7. 高效排查套路(建议你照着做))
  • [8. 进阶小技巧(可选但很实用)](#8. 进阶小技巧(可选但很实用))
  • [9. 总结](#9. 总结)
  • 参考资料(可扩展阅读)

1. GDB 是什么?能解决什么问题?

GDB(GNU Debugger)是 Linux 平台最常用的程序调试器之一,主要用来:

  • 断点调试:在指定代码行/函数处暂停,观察程序状态。
  • 单步执行:一行一行执行,定位逻辑错误。
  • 查看/修改变量:实时查看局部变量、参数、全局变量,必要时可临时修改变量值验证思路。
  • 调用栈回溯 :程序崩溃后查看调用链(bt/where),快速定位问题入口。
  • Core Dump 事后分析:程序崩溃生成 core 文件后,用 GDB 还原"事故现场"。

适用场景:段错误(SIGSEGV)、非法访问、野指针、栈溢出、数组越界、use-after-free 等。


2. 编译准备:一定要带调试信息

调试/分析崩溃时,可执行文件与崩溃现场必须匹配(同版本、同编译产物)。建议:

bash 复制代码
# 推荐:关闭过度优化,保留调试信息
gcc -g -O0 main.c -o app
# 或者 C++
g++ -g -O0 main.cpp -o app
  • -g:生成调试符号(行号、变量名、函数名)
  • -O0 / -Og:降低优化程度,避免变量被优化掉导致 <value optimized out>

3. GDB 常用命令速查(高频)

3.1 启动与加载

bash 复制代码
# 方式1:直接调试可执行文件
gdb ./app

# 方式2:带参数启动(也可在 gdb 内 set args)
gdb --args ./app arg1 arg2

# 方式3:调试 core 文件(事后分析)
gdb ./app /path/to/core
# 或
gdb -c /path/to/core ./app

3.2 断点/运行控制

命令 缩写 作用
break <位置> b 设置断点(行号/函数名/文件:行号)
info breakpoints i b 查看断点列表
delete <编号> d 删除断点
run r 启动程序(命中断点会停住)
continue c 继续运行到下一个断点/结束
next n 单步执行(不进入函数)
step s 单步执行(进入函数)
finish 跑完当前函数并返回到上一层
until u 运行到指定行/跳出循环场景常用
quit q 退出 gdb

常见断点位置写法:

gdb 复制代码
(gdb) b main
(gdb) b 20
(gdb) b main.c:20
(gdb) b foo if x > 10

3.3 查看代码/栈/变量

命令 缩写 作用
list l 显示源代码(可 l 1 从第1行)
where / backtrace bt 查看调用栈
bt full 调用栈 + 每帧局部变量(core 分析很有用)
frame <n> f 切换到第 n 层栈帧
up / down 在栈帧之间上下移动
print <表达式> p 打印变量/表达式值
display <表达式> 每次停住自动打印
info locals 打印当前栈帧所有局部变量
info args 打印当前函数参数
info registers 查看寄存器

3.4 内存查看(定位越界/野指针很关键)

x(examine)用于按格式查看内存:

gdb 复制代码
# x/<数量><格式><单位> <地址>
(gdb) x/16xb ptr      # 16字节,按16进制byte显示
(gdb) x/8xw ptr       # 8个word(4字节),按16进制显示
(gdb) x/s ptr         # 按字符串显示
(gdb) x/i $pc         # 反汇编当前指令

4. 实战:用 GDB 定位段错误(SIGSEGV)

4.1 构造一个会崩溃的例子

main.c

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *p = NULL;
    *p = 123; // 对 NULL 解引用,触发段错误
    return 0;
}

编译运行:

bash 复制代码
gcc -g -O0 main.c -o app
./app

4.2 用 GDB 运行并定位

bash 复制代码
gdb ./app

在 gdb 中:

gdb 复制代码
(gdb) run
Program received signal SIGSEGV, Segmentation fault.

(gdb) bt
#0  main () at main.c:7

(gdb) list

(gdb) info locals

(gdb) p p
$1 = (int *) 0x0

这类问题的定位套路:

  • bt 看栈:崩溃点在哪个函数、哪一行。
  • frame/list 看上下文:看崩溃行附近逻辑。
  • 最后 p/info locals/info args:确认关键指针、数组下标、长度参数是否异常。

5. Core Dump:程序崩了也能"回放现场"

当程序崩溃时,系统可把当时的内存映射、寄存器、栈等信息写入 core 文件,用于事后分析。

5.1 开启 core 文件生成(Linux)

bash 复制代码
# 查看当前限制(0 表示不生成)
ulimit -c

# 临时开启(当前 shell 生效)
ulimit -c unlimited

core 文件路径与命名常由内核参数控制:

bash 复制代码
cat /proc/sys/kernel/core_pattern

注意:线上环境经常被 systemd 接管 core,core 可能不落在当前目录。需要结合发行版策略确认落盘位置。

5.2 使用 GDB 分析 core

假设生成了 core 文件:

bash 复制代码
gdb ./app core

高频排查命令:

gdb 复制代码
(gdb) bt
(gdb) bt full
(gdb) info threads
(gdb) thread apply all bt
(gdb) frame 0
(gdb) info locals
(gdb) info args
(gdb) p some_ptr
(gdb) x/32xb some_ptr

如果看到类似提示:

  • no debugging symbols found:二进制没有 -g 调试符号
  • warning: core file may not match specified executable file:core 与可执行文件版本不匹配

6. 段错误(Segmentation fault)常见原因总结

段错误本质:访问了不允许访问的内存区域(地址不存在或受保护)。典型原因:

  • 空指针/野指针解引用char *p = NULL; *p = 'x';
  • 已释放内存再次使用(use-after-free)
  • 数组越界/指针越界:写穿栈/堆,导致随机崩溃
  • 返回局部变量地址:函数返回后栈帧销毁,地址失效
  • 栈溢出:递归太深、局部数组过大
  • 字符串处理长度错误 :如 sprintf 等导致溢出(建议 snprintf

7. 高效排查套路(建议你照着做)

7.1 现场调试(可复现崩溃)

  • 先断点b mainb 可疑函数
  • 单步逼近n/s
  • 观察关键数据pinfo localsinfo args

7.2 事后分析(只有 core)

  • gdb ./app core
  • bt full 一步到位获取:崩溃行 + 参数 + 局部变量
  • x/ 查看指针指向内存是否合理
  • 多线程程序:info threads + thread apply all bt

7.3 变量被优化掉怎么办?

如果出现:<value optimized out>

  • 编译时用 -O0-Og
  • 确保带 -g

8. 进阶小技巧(可选但很实用)

gdb 复制代码
# 让长数组/长字符串完整打印(默认可能截断)
(gdb) set print elements 0

# 打印结构体更友好
(gdb) set print pretty on

# 查看动态库与映射
(gdb) info sharedlibrary
(gdb) info proc mappings

9. 总结

  • GDB = 运行时调试 + 崩溃现场还原 的核心工具。
  • -g、尽量 -O0/-Og,能显著提升定位效率。
  • 段错误优先用:btlistinfo locals/argsp/x 的套路。
  • Core Dump 是线上排查的关键:可执行文件必须与 core 匹配

参考资料(可扩展阅读)

相关推荐
fufu03113 小时前
Linux环境下的C语言编程(四十六)
linux·运维·服务器
qq_418247884 小时前
Linux上部署conda环境
linux·运维·神经网络·机器学习·conda
FMRbpm4 小时前
串练习--------535.TinyURL的加密和解密
数据结构·c++·新手入门
wdfk_prog5 小时前
[Linux]学习笔记系列 -- [fs]dcache
linux·数据库·笔记·学习·ubuntu
GoWjw5 小时前
在C&C++中结构体的惯用方法
c语言·开发语言·c++
明洞日记5 小时前
【VTK手册027】VTK 颜色连续映射:vtkColorTransferFunction 深度解析与实战指南
c++·图像处理·算法·vtk·图形渲染
Bruce_kaizy5 小时前
c++单调数据结构————单调栈,单调队列
开发语言·数据结构·c++
默凉5 小时前
win 制作vs离线安装包
c++
fufu03115 小时前
Linux环境下的C语言编程(四十三)
linux·c语言·算法