前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Linux】段错误(核心已转储)(core dumped)问题的分析方法

【Linux】段错误(核心已转储)(core dumped)问题的分析方法

作者头像
程序员洲洲
发布2024-06-14 13:06:43
2890
发布2024-06-14 13:06:43
举报
文章被收录于专栏:项目文章项目文章

😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。

前言

在Linux系统中,程序运行时可能会遇到段错误(Segmentation Fault),这是一种常见的运行时错误,通常由于程序试图访问其内存空间中未分配(或不允许)的部分时发生。

当段错误发生时,系统可能会生成一个核心转储(core dump),它是一个包含程序终止时的内存映像的文件,可以用于后续的调试和问题分析。 本文将探讨如何分析段错误,并利用核心转储文件定位问题。

一、段错误概述

段错误发生的原因可能包括但不限于:

  • 指针访问无效的内存地址。
  • 栈溢出,例如递归调用太深。
  • 违反了内存保护规则。
  • 内存越界(数组越界,变量类型不一致等) 访问到不属于你的内存区域。
  • 访问系统数据区,尤其是往系统保护的内存地址写数据,最常见的就是给一个指针以0地址。
  • 多线程程序使用了线程不安全的函数。
  • 多线程读写的数据未加锁保护。对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成core dump
  • 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内存的开始地址不是按照这种结构或类型对齐的,那么访问它时 就很容易因为bus error而core dump.
  • 缓存溢出也可能引起“段错误”,对于这种while(1) {do}的程序,这个问题最容易发生,多此sprintf或着strcat有可能将某个buff填满,溢出,所以每次使用前,最好memset一下,不过 要是一开始就是段错误,而不是运行了一会儿出现的,缓存溢出的可能性就比较小。

段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gd tr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的 gdt表,后13位保存 相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向 的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的

一旦一个程序发生了越界访问,cpu就会产生相应的保护,于是segmentation fault就出现了通过上面的解释,段错误应该就是访问了不可访问的内存,这个内存区要么是不存在的,要么是受到系统保护的,还有可能是缺少文件或者文件损坏。# 二、核心转储文件

当程序因段错误而终止时,如果系统配置允许生成核心转储,将创建一个core文件(或类似的命名模式),这个文件包含了程序终止时的内存映像。

核心转储的配置

其实系统会在程序崩溃的那一刹那将整个内核的信息记录在一个文件里边,(ls 并不会看到这个文件)

确保/proc/sys/kernel/core_pattern配置允许生成核心转储文件。

设置ulimit以允许生成核心文件:

代码语言:javascript
复制
/etc/profile中加入以下一行,这将允许生成coredump文件
ulimit-c unlimited

编译的时候一定要加入-g选项,要不然在最后显示错误的时候只会显示错的地址,而不会显示错误的具体信息。

/proc/sys/kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作为扩展。文件内容为1,表示添加pid作为扩展名,生成的core文件格式为core.xxxx;为0则表示生成的core文件同一命名为core。

可通过以下命令修改此文件:

代码语言:javascript
复制
echo "1" > /proc/sys/kernel/core_uses_pid

一般core路径和可执行程序一个路径。

除此之外,还可以在/proc/sys/kernel/core-pattern里设置core文件的文件名模板。

代码语言:javascript
复制
echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern

三、分析段错误的步骤

  1. 确认核心转储文件的存在 当程序崩溃时,检查当前目录或core_pattern指定的位置是否有核心转储文件生成。
  2. 使用调试器分析核心转储 使用gdb(GNU Debugger)或其他调试器加载核心转储文件和相应的程序可执行文件,分析崩溃时的调用栈和变量状态。
代码语言:javascript
复制
gdb /path/to/program /path/to/coredump
  1. 检查调用栈 在gdb中,使用backtrace(或简写为bt)命令查看崩溃时的调用栈。
  2. 检查变量和寄存器状态 使用print(或简写为p)命令检查特定变量的值,使用info registers查看寄存器状态。
  3. 逐行检查源代码 根据调用栈信息,定位到源代码中的具体行号,检查相关代码逻辑。
  4. 考虑内存访问模式 分析程序的内存访问模式,检查是否有越界访问、错误的指针操作等。
  5. 运行时环境检查 确认程序运行时的配置和环境是否可能导致段错误。
  6. 编译器和链接器选项 使用-g选项编译程序,确保调试信息的完整性。使用valgrind等工具检查内存错误。

注意事项

  • 及时更新系统和工具:确保使用的是最新版本的操作系统、编译器和调试工具。
  • 详细记录错误信息:记录段错误发生时的完整堆栈跟踪和其他相关信息。
  • 多角度分析:从代码、数据和运行环境多个角度分析问题。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、段错误概述
    • 核心转储的配置
    • 三、分析段错误的步骤
    • 注意事项
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档