C/C++ CoreDump配合gdb分析程序崩溃教程

发布时间:2023-07-23 14:04:34 作者:yexindonglai@163.com 阅读(925)

什么是 Core dump

Core dump(核心转储)是在程序发生严重错误或崩溃时,操作系统将程序的内存状态和其他相关信息保存到一个文件中的过程。这个文件被称为核心转储文件或核心文件。核心转储文件记录了程序在崩溃时的内存映像、寄存器的值、堆栈信息以及其他相关信息。

核心转储文件对于调试程序崩溃和分析崩溃原因非常有用。通过分析核心转储文件,可以了解程序在崩溃时的状态,帮助开发人员定位和修复错误。

在大多数操作系统中,默认情况下,核心转储功能是启用的。当程序发生崩溃时,操作系统会尝试生成一个核心转储文件。生成核心转储文件的行为和设置可以通过操作系统的配置进行调整,包括核心转储文件的大小限制、保存位置和命名规则等。

请注意,核心转储文件可能会包含敏感信息,如程序的内存内容和寄存器值。因此,在生产环境中,通常会将核心转储文件的生成和访问权限限制为仅限于特定的管理员或开发人员。

只有程序崩溃了才会生成CoreDump吗?

通常情况下,核心转储文件(Core Dump)是在程序崩溃时生成的。当程序发生严重错误或崩溃时,操作系统会捕获程序的内存状态和其他相关信息,并将其保存到核心转储文件中。

然而,有些操作系统也允许手动触发生成核心转储文件,而不需要程序崩溃。这可以通过发送特定的信号给正在运行的程序来实现,例如使用以下命令。这将导致程序生成核心转储文件,而不会导致程序崩溃。

  1. kill -SIGQUIT <进程ID>

一、前置工作

1、核心文件说明

核心文件是在程序异常终止时生成的一种文件,用于记录程序崩溃时的内存映像。它包含了程序在崩溃时的内存状态、寄存器的值、堆栈信息以及其他相关信息。核心文件对于调试程序崩溃和分析崩溃原因非常有用。

2、设置核心文件存放地址

在 Linux 系统上,可以通过修改 /proc/sys/kernel/core_pattern文件来指定核心文件的命名模式和保存位置。可以使用 sysctl 命令来修改该文件,例如

  1. # 其中,%e 表示程序的文件名称,%p 表示进程的pid
  2. sysctl -w kernel.core_pattern=/root/core/core.%e.%p

也可以手动修改/proc/sys/kernel/core_pattern文件来达到目的

  1. echo "/root/core/core.%e.%p" > /proc/sys/kernel/core_pattern
3、设置核心文件大小

核心文件大小是指生成的核心文件的最大大小限制。当程序崩溃时,操作系统会尝试生成一个核心文件,但如果核心文件的大小超过了设定的限制,那么核心文件就不会被生成。核心文件大小的限制可以通过 ulimit -c 命令来设置;
核心文件大小有以下可选值;

  1. # 设置核心文件大小为0,也就是不生成核心文件,这也是系统默认值;
  2. ulimit -c 0
  3. # 设置核心文件大小为无限制,允许操作系统生成任意大小的核心文件。这对于调试程序崩溃和分析崩溃原因非常有用,因为可以获取更多的内存映像和相关信息。
  4. ulimit -c unlimited

在这里我们需要将核心文件大小设为 unlimited,这样才会生成核心文件;

二、模拟程序崩溃

1、准备崩溃程序

首先我准备好一个可以确保会崩溃的程序,对空指针对象直接赋值操作一定会导致程序崩溃;
main.cpp文件内容如下

  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4. int * a_ptr = NULL;
  5. int i = 1;
  6. *a_ptr = i; // 运行到这一步一定会崩溃退出
  7. cout<<"success"<<endl;
  8. }
2、编译并运行

然后输入以下命令进行编译

  1. # 编译
  2. g++ -g main.cpp -o main
  3. # 运行
  4. ./main

编译好之后就可以看到有个绿色的main文件,运行后不出所料,程序崩溃了,提示信息:

  1. # 括号里面的 (core dumped)表示已经将核心转储文件已经生成了;
  2. Segmentation fault (core dumped)

接下来我们进入核心文件的目录,发现核心文件已经生成了,叫做core.main.2869,其中2869就是程序运行时的进程id

3、使用 gdb 分析核心转储文件

怎么分析呢,格式如下,注意可执行文件和核心转储文件的中间有个空格

  1. gdb 编译后的可执行文件 核心转储文件

根据以上的公式套用下即可

  1. gdb main /root/core/core.main.2869

打印结果如下图,可以看到,直接就告诉你是是哪一行导致的崩溃;

如果还想要查看更详细的堆栈信息,可以用frameinfo frame指令

还可以通过print查看变量的值是多少

关键字c++