GDB 调试
使用 GDB 调试 “核心已转储” (Core Dumped) 问题
当程序出现 “核心已转储” (Segmentation fault, core dumped) 错误时,GDB (GNU Debugger) 是最强大的调试工具之一。以下是完整的调试流程:
1. 确保系统生成 core 文件
bash
# 检查当前 core 文件大小限制
ulimit -c# 如果显示 0,表示不生成 core 文件,设置为 unlimited
ulimit -c unlimited# 永久生效(添加到 ~/.bashrc 或 /etc/security/limits.conf)
echo "ulimit -c unlimited" >> ~/.bashrc
source ~/.bashrc# 设置 core 文件命名格式(可选)
echo "core.%e.%p.%t" > /proc/sys/kernel/core_pattern
2. 使用 GDB 调试 core 文件
bash
gdb 你的程序名 core文件
# 例如:
gdb ./my_program core.my_program.12345
3. 常用 GDB 命令
gdb
# 查看崩溃时的堆栈信息
bt # 或 backtrace# 查看详细的堆栈信息
bt full# 查看某个帧(frame)的详细信息
frame N # N 是帧编号# 查看变量值
print 变量名# 查看源代码
list# 查看寄存器的值
info registers# 查看内存
x/10xw 内存地址 # 查看10个word(4字节)的内存,16进制显示# 反汇编当前函数
disassemblesi ni run continue print
4. 常见崩溃原因分析
4.1 空指针解引用
gdb
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401234 in main () at test.c:10
10 printf("%d\n", *ptr); # ptr 是 NULL
4.2 数组越界
gdb
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401256 in main () at test.c:15
15 arr[100] = 10; # 数组大小只有10
4.3 使用已释放内存
gdb
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401289 in main () at test.c:20
20 free(ptr); # ptr 已经被释放过
4.4 栈溢出
gdb
Program received signal SIGSEGV, Segmentation fault.
0x00000000004012a1 in recursive_func () at test.c:30
30 recursive_func(); # 无限递归
5. 高级调试技巧
5.1 条件断点
gdb
break test.c:50 if i == 100
5.2 观察点
gdb
watch variable_name # 变量变化时中断
rwatch variable_name # 变量被读取时中断
awatch variable_name # 变量被读写时中断
5.3 多线程调试
gdb
info threads # 查看所有线程
thread N # 切换到线程N
thread apply all bt # 查看所有线程的堆栈
6. 预防措施
编译时添加调试信息:bash
gcc -g -O0 -Wall -Wextra -o my_program my_program.c
使用静态分析工具:bash
gcc -Wall -Wextra -fsanitize=address -g my_program.c
使用 Valgrind 检测内存问题:bash
valgrind --leak-check=full ./my_program
7. 实际案例演示
假设我们有以下导致段错误的程序 (segfault.c):c
#include <stdio.h>int main() {int *ptr = NULL;*ptr = 10; // 这里会导致段错误return 0;
}
调试步骤:bash
# 编译
gcc -g -o segfault segfault.c# 运行生成 core 文件
./segfault# 使用 GDB 调试
gdb ./segfault core# 在 GDB 中运行命令
(gdb) bt
# 会显示崩溃发生在 main 函数,第5行(gdb) list
# 查看源代码上下文(gdb) print ptr
# 会显示 ptr = 0x0 (NULL)
通过这样的分析,我们很快就能定位到问题所在。
=========================================
在 Linux 中生成 core dump 文件的完整指南
当程序崩溃时,core dump 文件包含了程序崩溃时的内存状态,是调试的重要资源。以下是生成和使用 core 文件的详细方法:
1. 确保系统允许生成 core 文件
1.1 检查当前设置
bash
ulimit -c
如果返回 0,表示禁止生成 core 文件如果返回 unlimited 或其他数字,表示允许生成1.2 临时启用 core 文件生成
bash
ulimit -c unlimited # 当前会话有效
1.3 永久启用 core 文件生成
bash
# 添加到 ~/.bashrc 或 ~/.bash_profile
echo "ulimit -c unlimited" >> ~/.bashrc
source ~/.bashrc# 或者全局设置(需要root权限)
echo "* soft core unlimited" >> /etc/security/limits.conf
2. 设置 core 文件存储位置和命名格式
2.1 查看当前设置
bash
cat /proc/sys/kernel/core_pattern
常见返回值:core:在当前目录生成名为 core 的文件/var/coredump/core.%e.%p:在指定目录生成带程序名和PID的文件2.2 修改 core 文件存储位置(临时)
bash
# 设置 core 文件存储到 /tmp 目录,并包含程序名、PID和时间戳
echo "/tmp/core.%e.%p.%t" > /proc/sys/kernel/core_pattern
2.3 永久修改 core 文件设置
bash
# 编辑 /etc/sysctl.conf
echo "kernel.core_pattern=/var/coredump/core.%e.%p.%t" >> /etc/sysctl.conf
echo "kernel.core_uses_pid=1" >> /etc/sysctl.conf# 创建 core 文件目录并设置权限
sudo mkdir -p /var/coredump
sudo chmod 777 /var/coredump# 使配置生效
sudo sysctl -p
2.4 core_pattern 格式说明
%e:可执行文件名%p:进程ID%t:时间戳%u:用户ID%g:组ID%s:导致dump的信号
3. 测试 core 文件生成
3.1 创建一个会崩溃的测试程序
c
// crash.c
#include <stdio.h>
int main() {int *ptr = NULL;*ptr = 42; // 这里会引发段错误return 0;
}
3.2 编译并运行
bash
gcc -g -o crash crash.c # 必须加-g选项保留调试信息
./crash
你应该会看到:text
Segmentation fault (core dumped)
3.3 检查 core 文件
bash
ls -lh /var/coredump/ # 或你设置的core文件目录
# 应该能看到类似 core.crash.12345.1620000000 的文件
4. 使用 GDB 分析 core 文件
bash
gdb ./crash /var/coredump/core.crash.12345.1620000000
在 GDB 中运行以下命令:gdb
bt # 查看调用栈
frame N # 查看特定栈帧
list # 查看源代码
print ptr # 查看变量值
5. 常见问题解决
5.1 没有生成 core 文件
可能原因:存储目录不可写bash
chmod 777 /var/coredump
磁盘空间不足bash
df -h
文件系统挂载选项限制bash
mount | grep noexec
5.2 core 文件太大
可以限制 core 文件大小:bash
ulimit -c 1000000 # 限制为1GB
5.3 多线程程序调试
bash
gdb -p <PID> # 附加到运行中的进程
thread apply all bt # 查看所有线程的堆栈
6. 高级配置
6.1 按用户限制 core 文件大小
bash
# 编辑 /etc/security/limits.conf
username soft core 1000000 # 用户username限制1GB
* hard core 0 # 其他用户禁止生成
6.2 使用 systemd-coredump
现代 Linux 发行版可能使用 systemd 管理 core 文件:bash
# 查看存储的 core dump
coredumpctl list# 使用 GDB 分析最近的 core dump
coredumpctl debug
6.3 压缩 core 文件
bash
echo "|/usr/bin/gzip > /var/coredump/core.%e.%p.gz" > /proc/sys/kernel/core_pattern
通过以上设置,你可以有效地生成和分析 core dump 文件,快速定位程序崩溃的原因。