什么是Segmentation fault(Core Dump)

本文详细解释了CoreDump的概念及用途,介绍了如何通过修改ulimit设置确保CoreDump文件的生成,并利用gdb工具进行错误定位。同时,还总结了导致程序出现CoreDump的常见原因,包括内存访问越界、多线程安全问题等。

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

什么是Core Dump?
Core的意思是内存, Dump的意思是扔出来, 堆出来.
开发和使用Unix程序时, 有时程序莫名其妙的down了, 却没有任何的提示(有时候会提示core dumped). 这时候可以查看一下有没有形如core.进程号的文件生成, 这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考.
core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump.

如何使用core文件?
gdb -c core文件路径 [应用程序的路径]
进去后输入where回车, 就可以显示程序在哪一行down掉的, 在哪个函数中.

为什么没有core文件生成呢?
有时候程序down了, 但是core文件却没有生成. core文件的生成跟你当前系统的环境设置有关系, 可以用下面的语句设置一下, 然后再运行程序便成生成core文件.
ulimit -c unlimited
没有找到core文件,我们改改ulimit的设置,让它产生。1024是随便取的,要是core文件大于1024个块,就产生不出来了。)
$ ulimit -c 1024 (转者注: 使用-c unlimited不限制core文件大小

core文件生成的位置一般于运行程序的路径相同, 文件名一般为core.进程号

4. 用gdb查看core文件:
下面我们可以在发生运行时信号引起的错误时发生core dump了.
发生core dump之后, 用gdb进行查看core文件的内容, 以定位文件中引发core dump的行.
gdb [exec file] [core file]
如:
gdb ./test test.core
在进入gdb后, 用bt命令查看backtrace以检查发生程序运行到哪里, 来定位core dump的文件->行.

===========================================================================

造成程序core dump的原因很多,这里根据以往的经验总结一下:

1 内存访问越界

  a) 由于使用错误的下标,导致数组访问越界

  b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符

  c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。

 

2 多线程程序使用了线程不安全的函数。

应该使用下面这些可重入的函数,尤其注意红色标示出来的函数,它们很容易被用错:

asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n) ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c) getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c) fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c) getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3) getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n) nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3) getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c) getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c) getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)

 

3 多线程读写的数据未加锁保护。

对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成core dump

 

4 非法指针

  a) 使用空指针

  b) 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时就很容易因为bus error而core dump.

 

5 堆栈溢出

不要使用大的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。
### 关于 Segmentation FaultCore Dump 的原因及解决方案 #### Segmentation Fault 错误的原因 Segmentation fault 是一种常见的程序运行时错误,表明程序尝试访问未分配给它的内存区域。这可能是由于以下几种情况引起的: - **指针操作不当**:使用空指针或悬空指针可能导致非法内存访问[^2]。 - **数组越界**:当索引超出数组边界时会引发此类错误。 - **栈溢出**:函数调用层次太深或者局部变量占用过多空间可能会导致堆栈溢出[^1]。 这些因素都可能造成程序崩溃并生成 core dump 文件作为调试依据。 #### Core Dump 文件的作用与配置 Core dump 文件是在发生致命信号(如 SIGSEGV)之后创建的一个二进制文件,它包含了进程被终止那一刻的状态信息,对于开发者来说是非常宝贵的诊断工具。为了更好地利用 core dumps 进行故障排查,可以采取如下措施: - **启用核心转储功能** - Linux 系统默认情况下不会自动保存 core 文件,可以通过设置 `ulimit` 参数来允许其生成: ```bash ulimit -c unlimited ``` - **指定 core 文件的位置和命名规则** - 使用 `/proc/sys/kernel/core_pattern` 来定义 core 文件的存储位置以及如何命名它们。例如,要将所有的 core 文件存放在特定目录下,并按照时间戳重命名,则可以在该文件中写入类似于 `%t-%e.core` 的模式字符串。 #### 解决 Segmentation Fault 的方法 针对上述提到的各种潜在诱因,有几项通用策略可以帮助预防和修复 segmentation faults: - **静态分析工具的应用** - 工具如 cppcheck 或者 clang-tidy 可以帮助识别源码中存在的逻辑缺陷,在编译前即能发现一些潜在的风险点[^3]。 - **动态检测手段** - Valgrind 是一款强大的内存泄漏检查器兼调试辅助软件;AddressSanitizer 则专注于捕捉各种形式的记忆体破坏行为,两者均能在一定程度上协助定位问题所在之处。 - **借助 GDB 调试器** - 当应用程序抛出了 segmentation fault 后如果产生了相应的 core file ,那么可以直接加载到 GNU Debugger 中进一步探究根本原因。命令格式如下所示: ```bash gdb ./program_name /path/to/core_file bt full quit ``` 通过以上介绍的方法和技术,应该能够有效地处理大多数场景下的 segmentaion fault 报错现象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值