GDB 调试

发布于:2025-09-03 ⋅ 阅读:(14) ⋅ 点赞:(0)

使用 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 内存地址  # 查看10word(4字节)的内存,16进制显示

# 反汇编当前函数
disassemble

si 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 文件,快速定位程序崩溃的原因。