GDB分析core dump

本文介绍了coredump的概念及其在Linux系统中的触发方式,当程序出现段错误如Segmentfault时,操作系统会生成core文件。通过配置`ulimit`命令可以开启coredump功能。在coredump发生后,可以使用GDB调试工具结合core文件来查看程序崩溃的堆栈信息,通过`bt`命令回溯调用栈,找出问题所在。通过`frame`、`list`、`infolocals`和`print`命令可以进一步分析错误原因。这种方法对于排查涉及指针操作的内存错误非常有用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Core dump

core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump. (linux中如果内存越界会收到SIGSEGV信号,然后就会core dump)

在程序运行的过程中,有的时候我们会遇到Segment fault(段错误)这样的错误。这种看起来比较困难,因为没有任何的栈、trace信息输出。该种类型的错误往往与指针操作相关。往往可以通过这样的方式进行定位。

配置操作系统产生core文件

ulimit -c 或者 ulimit -a查看core file文件大小的配置情况

比如我在自己的Ubuntu系统随便打开一个终端

pc@mypc:~$ ulimit -a
core file size          					(blocks, -c) 0
data seg size          				 (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               						(blocks, -f) unlimited
pending signals                 	(-i) 62923
max locked memory       	(kbytes, -l) 65536
max memory size         		(kbytes, -m) unlimited
open files                    		  	(-n) 1024
pipe size            						(512 bytes, -p) 8
POSIX message queues    (bytes, -q) 819200
real-time priority              	(-r) 0
stack size              					(kbytes, -s) 8192
cpu time               					(seconds, -t) unlimited
max user processes            (-u) 62923
virtual memory          			(kbytes, -v) unlimited
file locks                      			(-x) unlimited

此时“core file size ”大小为0,说明终端没有打开core dump,解决方法:

ulimit -c unlimited(只对当前终端进程有效)
或在~/.bashrc 的最后加入: ulimit -c unlimited (一劳永逸)

使用gdb查看core文件

在发生了core dump之后,如何使用gdb查看core文件内容,以定位文件中引发core dump的行呢?
我们通过以下“test_gdb.cpp”代码说明,该代码中有一个很明显的数组越界错误

#include <iostream>

void fun(){
    char v[10];
    for(int i = 0; i <= 10; i++){
        v[i] = i;
    }
}

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

编译并运行程序

pc@mypc:~$ g++ -g main.cpp -o a.out
pc@mypc:~$ ./a.out 
段错误 (核心已转储)

意料之中,运行该代码的时候发生了段错误,系统捕捉这一错误并在终端所在文件夹里生成了core文件。接下来在同一个终端里输入:

  • gdb [exec file] [core file] 命令行格式打开gdb和生成的core文件
# gdb [exec file] [core file]
pc@mypc:~$ gdb ./a.out core
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./test_gdb...done.
[New LWP 31499]
Core was generated by `./test_gdb'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51	../sysdeps/unix/sysv/linux/raise.c: 没有那个文件或目录.

gdb的提示信息告诉我们错误发生在"…/sysdeps/unix/sysv/linux/raise.c:51"位置上,错误原因是"…/sysdeps/unix/sysv/linux/raise.c: 没有那个文件或目录.",这是由于数组越界发生的系统内部错误,我们不用管它。直接回溯(backtrace)错误发生的位置:

  • bt 回溯错误函数的调用关系
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007f7ad2fa1921 in __GI_abort () at abort.c:79
#2  0x00007f7ad2fea967 in __libc_message (action=action@entry=do_abort, 
    fmt=fmt@entry=0x7f7ad31178fb "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007f7ad3095b61 in __GI___fortify_fail_abort (need_backtrace=need_backtrace@entry=false, 
    msg=msg@entry=0x7f7ad31178d9 "stack smashing detected") at fortify_fail.c:33
#4  0x00007f7ad3095b22 in __stack_chk_fail () at stack_chk_fail.c:29
#5  0x0000559718536977 in fun () at /home/gao/Cpp_Projects/test_gdb/main.cpp:8
#6  0x0000559718536994 in main () at /home/gao/Cpp_Projects/test_gdb/main.cpp:14

gdb提示中每一条消息前边都有一个编号,其中很多都是系统内部函数的调用错误,但是我们只关心自己代码里边的问题。于是我们可以输入以下命令进行更进一步的调试:

  • frame [number] 单独查看某函数中的错误。
  • list 查看错误位置附近的代码
  • info locals 查看错误函数中的局部变量
  • print [var_name]p [var_name] 查看单独某一个变量的值
(gdb) frame 5
 #5  0x0000559718536977 in fun () at /home/gao/Cpp_Projects/test_gdb/main.cpp:8
8	}
(gdb) list
	3	void fun(){
	4	    char v[10];
	5	    for(int i = 0; i <= 10; i++){
	6	        v[i] = i;
	7	    }
	8	}
	9	
	10	int main() {
	11	    int a,b;
	12	    a = 0;
(gdb) info locals 
v = "\000\001\002\003\004\005\006\a\b\t"
(gdb) print v
$1 = "\000\001\002\003\004\005\006\a\b\t"

通过该gdb+core dump file的方法就可以大概定位到错误发生的位置了。

<think>好的,我现在需要回答用户关于如何使用GDB调试工具分析core dump文件的教程和步骤的问题。用户已经提供了一些参考资料,我需要整合这些信息,并按照他们给的系统级指令来组织回答。 首先,我要确保遵循用户的格式要求。所有行内数学表达式用$...$,不过这个问题可能不涉及数学公式,但需要检查是否有变量或技术术语需要用这种格式。例如,如果有代码中的变量名,可能不需要,但如果有类似参数或数学表达式,可能需要使用。不过根据参考资料,这里可能更多是命令行和步骤,可能不需要数学表达式,但需要保持警惕。 独立公式需要用$$...$$,但同样,这个问题可能不涉及,但需要留意是否有需要的地方。不过根据问题内容,可能不需要,所以暂时可以忽略这点。 必须使用中文回答,生成相关问题,回答中引用的段落末尾添加引用标识。用户还提到要结构清晰,分步骤解决问题,尽量真实可靠。 接下来,我需要整理用户提供的引用内容: 引用[1]提到编写测试代码、生成core文件分析的过程,涵盖了每个步骤的具体操作。引用[2]是关于GDB分析core文件的教程,并提到更多GDB调试的内容。引用[3]涉及VSCode在Docker内调试core文件的步骤,包括安装工具和配置。引用[4]提到检查GDB版本的方法,以及安装GDB的步骤。 用户的问题是询问使用GDB分析core dump文件的教程和步骤,所以需要综合这些信息,分步骤说明。 首先,需要生成core dump文件,这涉及到系统设置,如ulimit命令,可能还要设置core文件的存储路径。然后,使用GDB加载可执行文件core文件进行调试,查看堆栈跟踪等信息。可能还需要检查GDB是否安装正确,版本是否合适。另外,用户可能还想知道如何配置环境,比如在VSCode或Docker中的调试方法,但用户的问题主要集中在GDB本身,所以可能先重点讲命令行步骤,再提到其他工具的参考。 现在,按照步骤来组织: 1. 确保系统生成core dump文件:需要设置ulimit -c unlimited,可能还要配置core文件的名称和路径,比如通过修改/proc/sys/kernel/core_pattern。 2. 复现程序崩溃:运行程序直到崩溃,生成core文件。 3. 使用GDB分析core文件:命令格式是gdb <可执行文件> <core文件>,然后使用bt查看堆栈跟踪,检查变量状态等。 4. 检查GDB版本和安装:确保GDB已安装,版本兼容。 可能还需要提到如何编译程序时加入调试信息(-g选项),这在引用[1]中提到编写测试代码时需要加上-g,这样才能有符号信息供调试。 然后,引用中的各个步骤需要对应到这些部分,比如引用[1]中的生成core文件过程,引用[2]中的GDB分析步骤,引用[4]中的检查GDB版本,引用[3]可能涉及其他工具,但用户问题主要关注GDB本身,所以可能作为附加内容简要提及。 在生成相关问题部分,可以包括如何配置系统生成core文件、如何编译程序以便调试、如何解读GDB输出的堆栈跟踪,以及VSCode或Docker中的调试方法等。 现在需要确保回答结构清晰,分步骤,每个步骤说明详细,并在适当的地方添加引用标记。例如,当提到生成core文件时,引用[1]和[4]可能相关;使用GDB命令时引用[2]和[4]。 此外,要检查是否有遗漏的步骤,比如编译时的-g选项,处理core文件的位置,权限问题等。可能还需要说明如何确认core文件是否正确生成,以及如何定位core文件的位置。 总结,回答的大纲可能是: 1. 准备调试环境 a. 安装GDB b. 编译程序时添加调试信息(-g) c. 启用core dump生成(ulimit和core_pattern) 2. 生成core dump文件 a. 运行程序导致崩溃 b. 确认core文件生成 3. 使用GDB分析core文件 a. 启动GDB并加载可执行文件core文件 b. 常用命令(bt、frame、print等) c. 分析堆栈跟踪和变量状态 4. 其他工具或环境中的调试(如VSCode、Docker,简要提及并引用相关资源) 然后,相关问题可能涉及每一步的细节,如如何设置ulimit永久生效,如何解读堆栈跟踪,优化调试体验的方法,或特定环境下的调试配置。 需要确保引用标记正确,例如,当提到生成core文件的步骤时,引用[1]和[4],当提到GDB命令时引用[2]和[4],VSCode配置引用[3]。 现在,按照这个思路组织内容,确保每个步骤清晰,引用正确,并且语言符合中文习惯,不使用Markdown格式,但用户提供的示例中使用了代码块,所以需要包含代码块,如示例中的Python代码。但在这个问题中,可能涉及命令行操作,所以用代码块显示命令,例如: ```bash gdb ./my_program core ``` 最后,生成相关问题,如: 1. 如何配置系统永久启用core dump生成? 2. 使用GDB调试core文件时有哪些常用命令? 3. 如何在VSCode中配置GDB调试core dump文件? 等等。 现在需要将这些内容整合成一个连贯的回答,遵循用户的格式要求,确保所有引用正确,步骤详细。</think>### 使用GDB分析core dump文件的教程与步骤 #### 1. **准备调试环境** - **安装GDB** 确保系统已安装GDB调试工具。可通过以下命令安装: ```bash sudo apt-get install gdb # Ubuntu/Debian ``` 验证安装: ```bash gdb --version # 输出版本信息表示安装成功[^4] ``` - **编译程序时添加调试信息** 在编译代码时需使用`-g`选项生成调试符号: ```bash gcc -g -o my_program my_program.c ``` - **启用core dump生成** - 临时生效: ```bash ulimit -c unlimited # 解除core文件大小限制 ``` - 永久生效: 在`/etc/security/limits.conf`中添加`* soft core unlimited`。 - 设置core文件路径(可选): ```bash echo "/tmp/core.%t" | sudo tee /proc/sys/kernel/core_pattern # 指定存储路径[^1] ``` --- #### 2. **生成core dump文件** - **运行程序并触发崩溃** 执行程序直到崩溃,例如: ```bash ./my_program ``` 崩溃后会在指定路径(如`/tmp`)生成core文件(如`core.1234`)[^1]。 - **确认core文件生成** 检查文件是否存在: ```bash ls /tmp/core.* ``` --- #### 3. **使用GDB分析core文件** - **加载可执行文件core文件** ```bash gdb ./my_program /tmp/core.1234 ``` GDB会自动定位崩溃时的代码位置[^2]。 - **常用调试命令** - 查看堆栈跟踪: ```bash (gdb) bt # 显示函数调用栈[^2] ``` - 切换堆栈帧: ```bash (gdb) frame 2 # 切换到第2帧 ``` - 查看变量值: ```bash (gdb) print variable_name ``` - 分析寄存器状态: ```bash (gdb) info registers ``` --- #### 4. **其他工具与场景** - **VSCode调试配置** 在VSCode中安装C/C++扩展,配置`launch.json`以支持core dump调试[^3]。 - **Docker环境调试** 需确保容器内已安装GDB和调试符号,挂载core文件到容器路径。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值