【问题记录】Ubuntu 22.04 环境下,程序报:段错误(核心已转储)怎么使用 core 文件和GDB调试器 解决?

news2024/10/5 21:14:43

目录

环境

问题情况

解决思路

原因分析

解决方法

番外知识


  • VMware® Workstation 16 Pro (版本:16.1.2 build-17966106)
  • ubuntu-22.04.2-desktop-amd64

  • 本人在运行百万并发的服务端程序时,程序运行报:段错误(核心已转储),导致程序异常退出,如下

  • 首先要确定核心转储文件的生成路径和大小限制。然后使用调试器(如 GDB)来分析核心转储文件和堆栈跟踪信息后,修复代码中导致“段错误”的原因。

1.什么是段错误?

  • 段错误(Segmentation Fault)是一种常见的程序错误,通常在访问无效的内存地址时发生。当程序试图访问一个不属于它的内存段时,操作系统会发送一个信号(SIGSEGV(段错误信号))给程序,称为段错误。

2.可能产生段错误的情况

  • 内存访问错误:最常见的原因之一是程序试图访问无效的内存地址或未初始化的指针。这可能是由于代码错误、缓冲区溢出或内存越界等造成的。当程序尝试访问系统不允许访问的内存区域时,操作系统会引发段错误。
  • 无效的指令或操作:另一个常见原因是程序执行了无效的指令或操作。这可能是由于编译错误、错误的代码逻辑或架构不兼容性等引起的。当处理器尝试执行无效的指令或操作时,会导致段错误。
  • 动态内存分配问题:使用动态内存分配(如 malloc 或 new)时,如果出现内存泄漏、重复释放已释放的内存或访问已释放的内存等问题,可能导致段错误。这些问题可能是由于错误的内存管理导致的。
  • 栈溢出:如果程序的栈空间超出了其允许的范围,例如无限递归调用或大量局部变量使用导致的栈溢出,会产生段错误。
  • 库或依赖项问题:有时,段错误可能是由于使用损坏的库、不兼容的版本或缺少的依赖项引起的。库的错误使用或配置问题可能导致段错误。
  • 硬件问题:虽然比较罕见,但硬件故障(如内存损坏)也可能导致程序报告段错误并生成核心转储。

3.核心已转储是转储到那儿?

  • 当程序发生段错误时,操作系统会生成一个名为 core 或 core.<进程ID> 的核心转储文件,其中包含了程序崩溃时的内存映像和其他相关信息。这个core文件通常会被转储到当前工作目录下。
  • 但我的 core 文件并没有生成到程序的工作目录下,看下面解决...

1.检查操作系统的核心转储文件(core dump file)生成设置

  • 使用命令 ulimit -a 查看当前的核心转储文件大小限制和其他限制信息
  • 查找输出中的"core file size"(核心转储文件大小)字段,红框中的 0 表示当前禁用了核心转储文件的生成。可以更改这个限制来启用核心转储文件的生成。

2.更改 "core file size”字段 的限制来启用核心转储文件的生成

  • 使用 ulimit -c unlimited 命令可以将core文件的大小限制设置为无限制,但通过ulimit命令设置的参数仅在当前 shell 进程生效,也就是当前会话。一旦关闭终端窗口,设置将被重置为默认值。因此,这种修改并不是永久性的。不推荐
  • 如果想要在系统级别永久修改core文件的生成大小限制,需要进行操作系统的配置更改。可以通过修改 /etc/security/limits.conf 文件来设置core文件大小限制。添加或修改下面两行:
    • *    soft    core    unlimited
    • *    hard    core    unlimited
  • 重启虚拟机,重新加载系统的参数配置,以确保更改生效重启命令: sudo reboot

3.话不多说,直接测试一下

  • 不想跑服务端程序了,太费时了,直接写一个测试栗子,代码如下:
  • 运行该测试栗子后,并没有在工程目录下生成 core 文件。

4.确定一下 core 文件的生成路径

  • 查找资料说Linux 内核有一个参数 kernel.core_pattern,用于指定生成核心转储文件时的文件名和路径模式,相关的配置文件为/proc/sys/kernel/core_pattern。而在 Linux 中,可以使用 sysctl 命令来检查和更改核心转储文件的生成路径限制。
  • 然后使用 sysctl kernel.core_pattern 命令来查看当前的核心转储文件生成路径。它输出了下面一行内容:
    • kernel.core_pattern = |/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E
    • 上面这一行是啥意思呢,解释如下:
      • |/usr/share/apport/apport: 它是一个特殊的核心转储处理程序(core dump handler),它是一个用于收集和报告故障的工具。当进程收到 SIGSEGV 或类似的信号时,内核将使用 kernel.core_pattern 中指定的处理程序来处理和处理核心转储文件。
      • %p: 进程 ID。
      • %s: 目前正在运行的线程 ID。
      • %c: 产生核心转储文件的信号代码。
      • %d: 序列号,用于确保在同一目录中生成的核心转储文件具有唯一的名称。
      • %P: 父进程 ID。
      • %u: 用户名。
      • %g: 组名。
      • %E: 产生核心转储文件的可执行文件全路径。
    • 具体而言,/usr/share/apport/apport 是一个用于 Ubuntu 系统的工具,它可以收集有关崩溃和故障的信息,并生成相应的错误报告。

5.修改 core 文件的生成路径

  • 可以使用 sudo sysctl -w kernel.core_pattern=<path_to_directory>/core 命令将其恢复为期望的路径。确保 <path_to_directory> 是一个有效的目录路径。比如
    • sudo sysctl -w kernel.core_pattern=core
  • 重新编译一下,在当前目录下生成了 core.<进程ID> 的核心转储文件,如下
  • 注意:以上方式修改 kernel.core_pattern 的值只在运行时生效,并不是永久的,在系统重启后,该更改将被重置为默认值。
  • 可以了解最后一节“番外知识

6.使用调试工具 gdb 来加载和分析 core 文件

  • 生成核心文件:使用 gcc 编译记得加 -g 命令。
  • 加载核心文件:使用gdb命令行加载核心文件,将核心文件加载到调试环境中。
    • gdb <可执行文件路径> <核心文件路径>
  • 查看堆栈回溯:运行gdb后,使用bt命令(或backtrace)来查看堆栈回溯,它将显示程序在崩溃时的函数调用链。
    • (gdb) bt
  • 检查变量值:你可以使用print命令来检查变量的值。只需指定变量名即可查看其当前值。
    • (gdb) print variable_name
  • 跳转到特定帧:使用frame命令可以在堆栈帧之间进行导航,并查看在特定帧上的堆栈信息。帧编号通常是从0开始按逆序分配的,也就是最底部帧的编号是0。
    • (gdb) frame frame_number
  • 分析原因:分析堆栈回溯和变量值,可以帮助你定位程序崩溃的原因。一般情况下,最底部的堆栈帧提供了最初崩溃的位置。
  • 操作如下:说明 *P 未初始化

番外知识

1.对 /proc/sys/kernel/core_pattern 可以添加可写权限吗?

  • 答案是不可以。默认权限如下(所有者具有读写权限,组用户和其他用户只有读取权限)。
  • 对于/proc/sys/kernel/core_pattern文件,不能直接添加可读权限。这是因为/proc目录和其下的文件是虚拟文件系统(procfs)的一部分,用于提供对内核和进程信息的访问,它们的权限和所有权是由内核控制的,而不受Linux文件系统权限模型的限制。
  • /proc目录中,每个文件和目录的权限通常被设置为只读,不允许用户直接修改它们的权限。这是为了确保提供的信息的完整性和一致性,并防止对内核和进程状态的非授权更改。
  • 因此,无法通过常规的 chmod 命令或其他方式直接向 /proc/sys/kernel/core_pattern添加可读权限或更改其权限。尝试执行类似以下命令时会出现错误:
    • sudo chmod +w /proc/sys/kernel/core_pattern
  • 你会收到“Operation not permitted”或“不允许的操作”类似的错误消息。

2.在系统重启后,对 /proc/sys/kernel/core_pattern 文件的更改为什么被重置为默认值?

  • 这是因为/proc/sys/目录中的文件是在内核启动期间动态生成的,其值来自于内核参数或其他系统设置。在系统重启时,这些文件会重新加载为其默认值或由某些配置文件指定的值。

3.怎么实现永久性修改/proc/sys/kernel/core_pattern 文件呢?(这条有问题)

  • 编辑/etc/sysctl.conf文件:这种方式不太好,每次系统重启后要执行一下 sudo sysctl -p 命令才会修改/proc/sys/kernel/core_pattern的值
    • 可以编辑 /etc/sysctl.conf 文件,将核心转储文件模式的修改添加到该文件中,添加内容如下:
      • kernel.core_pattern = core
    • 在保存并退出文件后,使用以下命令重新加载配置,使新的核心转储文件模式生效:
      • sudo sysctl -p
  • 创建并编辑系统启动脚本:可以编写一个脚本,以在系统启动时将核心转储文件模式设置为所需的值。将脚本放置在适当的位置,例如/etc/init.d/目录,并设置为在系统启动时执行。(测试了没有用)
    • 创建启动脚本文件:在所选择的目录中创建一个新文件
      • sudo vim /etc/init.d/my_startup_script.sh
    • 编写启动脚本:在脚本中添加如下内容,保存成功并退出。
      • #!/bin/bash
      • echo "core" >> /proc/sys/kernel/core_pattern
      • exit 0
    • 赋予脚本执行权限:使用以下命令为启动脚本文件赋予执行权限
      • sudo chmod +x /etc/init.d/my_startup_script.sh
    • 配置启动脚本的执行:将启动脚本添加到系统的启动过程中,以确保在系统启动时执行
      • sudo update-rc.d my_startup_script.sh defaults
    • 若要禁用脚本的启动,可以使用以下命令(了解)
      • sudo update-rc.d -f my_startup_script.sh remove

注意

  • 需要注意的是,更改 /proc/sys/kernel/core_pattern 文件的权限和内容是敏感操作,可能会影响系统的稳定性和安全性。务必小心谨慎,并确保了解所做更改的影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/783425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

语音基石模型Speech Foundation Models

语音基石模型&#xff08;Speech Foundation Models&#xff09; 主要包含三部分&#xff1a; 1.语音表示学习&#xff08;Speech representation learning&#xff09; 自监督学习模型&#xff08;Self-suprevised learning, SSL model&#xff09;Representation benchmark…

CMU 15-445 -- Embedded Database Logic - 12

CMU 15-445 -- Embedded Database Logic - 12 引言User-Defined Functions (UDF)SQL FunctionsExternal Programming Language Stored ProceduresStored Procedures 与 UDF 的区别 Database TriggersChange NotificationsUser-Defined Types (UDT)Viewsviews vs select...intov…

区别出过孔的内径、外径、单边孔环、电镀铜厚

自记&#xff1a; 这个参数是啥&#xff1f;下图区别出过孔的内径、外径、单边孔环、电镀铜厚 嘉立创单双面最小过孔内径0.3mm/外径0.6mm&#xff08;极限0.56mm&#xff09;&#xff0c;四、六层最小过孔内径0.2mm/外径0.45mm&#xff08;极限0.40mm&#xff09;&#xff0c;外…

学习day50

自定义指令总结&#xff1a; 一&#xff1a;定义语法&#xff1a; (1)局部指令&#xff1a; new Vue({ directives{指令名&#xff0c;配置对象} }) 或 new Vue({ directives{指令名&#xff0c;回调函数} }) (2)全局对象 Vue.dir…

基于Gym Anytrading 的强化学习简单实例

近年来强化学习(RL)在算法交易领域受到了极大的关注。强化学习算法从经验中学习并基于奖励优化行动使其非常适合交易机器人。在这篇文章&#xff0c;我们将简单介绍如何使用Gym Anytrading环境和GME (GameStop Corp.)交易数据集构建一个基于强化学习的交易机器人。 强化学习是…

【Java从0到1学习】05 Java 数组

1. 数组概述 需求&#xff1a;现在需要统计某公司员工的工资情况&#xff0c;例如计算平均工资、找到最高工资等。假设该公司有80名员工&#xff0c;用前面所学的知识&#xff0c;程序首先需要声明80个变量来分别记住每位员工的工资&#xff0c;然后在进行操作&#xff0c;这样…

MySQL一些知识

六、MySQL命令参数 七、远程登录 use mysql 八、SQL语句和常见的SQL操作 九、数据库和表的创建及插入 指定字段名称&#xff0c;按照表的字段名称顺序写&#xff1a; 指定字段名称&#xff1a; 字段名称可以不全部指定&#xff1a;

SpringBoot(三)

文章目录 前言一.日志的作用二.日志的使用2.1 自定义日志打印三.日志的级别3.1 日志级别的作用3.2 日志级别的分类和使用 四.⽇志持久化 前言 日志在应用程序中扮演着至关重要的角色&#xff0c;它是软件开发、运维和故障排查中不可或缺的工具。无论是大型企业级应用还是小型个…

node插件的安装、HTTP协议

接口测试与UI测试&#xff08;功能测试&#xff0c;UI的自动化测试&#xff09;有什么区别&#xff1f; 1、接口测试更多测试的是客户端与后端之间的交互 2、接口测试也是可以完全的测试产品功能测试场景 UI测试&#xff1a; 1、页面的交互 2、页面的各种提示信息的验证 …

C#栈、List结构的简单搭建

1、栈是一种先进后出的结构&#xff0c;如图&#xff1a; 我们用代码&#xff0c;简单实现一下&#xff1a; public class StackTest<T>{private T[] stack { get; set; }public int length { get; set; }public StackTest(){length 0;stack new T[length];}public vo…

[JVM]String str1 = new String(“yhz“)和 String str2 = “yhz“ 的区别

文章目录 0、前情1、相同之处2、不同之处3、解释前情 0、前情 为什么str1 str2 就返回true&#xff0c;而str1str3 就返回false&#xff1f;先看内存图解释 1、相同之处 String str1new String(“yhz”)和String str2“yhz”&#xff0c;都会先去字符串常量池中查看是否已经存…

Helm KinD kubectl krew Istio急速安装

本篇更新网上许多安装失效的工具&#xff0c;如krew和KinD。 本篇测试使用时间为2023/7/20&#xff0c;基本都为最新版本或最新稳定版本。 前置 Helm 是 Kubernetes 的一个包管理工具&#xff0c;用于简化 Kubernetes 应用的部署和管理。Helm 使用名为 "chart" 的打…

QDialog的两种显示方式

QDialog的两种显示方式 模态显示非模态显示 QDialog不能嵌入到其他窗口中显示&#xff08;无论继承与否&#xff09; 模态显示 d->exec(); 阻塞程序的执行 非模态显示 d->show(); 不阻塞程序

A--玉米大炮--2022河南萌新联赛第(三)场:河南大学

输入 3 3 1 1 2 2 3 3 输出 0 说明 开始时,小蓝控制所有大炮立即发射炮弹,僵王博士受到 666 点伤害,直接被击溃。 示例2 输入 2 20 5 1 5 3 输出 2 说明 开始时,小蓝控制所有大炮立即发射炮弹,僵王博士受到 101010 点伤害, 一秒后一号大炮装填完毕,小蓝控制其攻击僵王…

力扣 -- 152. 乘积最大子数组

一、题目&#xff1a; 题目链接&#xff1a;152. 乘积最大子数组 - 力扣&#xff08;LeetCode&#xff09; 二、解题步骤 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 三、参考代码&#xff1a; class Solut…

分布式数据库 Join 查询设计与实现浅析

目录 前言&#xff1a; ①Mysql 分库分表 Join 查询场景 sharding-jdbc Code Insight SQL 路由策略 ②Elasticsearch Join 查询场景 elasticsearch-sql Code Insight ③More Than Join Join 算法 Elasticsearch Nested 类型 前言&#xff1a; 分布式数据库 Join 查…

Unity 2D 针对单个物体的空气墙(能指定物体的碰撞器)

笔者也是废了九牛二虎之力才发现这个API并选择一种相对效率高还简单的实现方法 克服了同层级空气墙的问题 这样可以实现只跟列表里的物体能发生碰撞 在使用之前请确保&#xff1a;空气墙 原本 可以与列表指定的物体发生碰撞 然后本脚本会自动取消列表外的全部碰撞&#xff…

使用spark进行hbase的bulkload

使用spark进行hbase的bulkload 一、 背景 HBase 是一个面向列&#xff0c;schemaless&#xff0c;高吞吐&#xff0c;高可靠可水平扩展的 NoSQL 数据库&#xff0c;用户可以通过 HBase client 提供的 put get 等 api 实现在数据的实时读写。在过去的几年里&#xff0c;HBase …

C++面向对象程序设计-基础入门(超详细)

目录 一、c概述 二、初识c 1、第一个c程序 2、c面向对象的三大特性&#xff08;重要&#xff09; 三、作用域运算符&#xff1a;&#xff1a; 1、使用关键字namespace创建一个命名空间 2、命名空间只能定义在全局 3、 命名空间嵌套 4、随时将新的成员加入命名空间 5、命…

uni-app : 监听路由变化

在App.vue中 在 onLaunch中,利用拦截器监听 navigateTo等, 切记要在 invoke回调函数中查看, 要是再 success回调函数中,都路由完成了,还看啥? onLaunch(){ uni.addInterceptor(navigateTo, { //监听跳转invoke(e) {console.log(******** invoke-navigateTo ********, e.url)}…