C++(Qt)软件调试---linux下生成/调试Core文件(3)

#软件调试

C++(Qt)软件调试—linux下生成/调试Core文件(3)

文章目录

  • C++(Qt)软件调试---linux下生成/调试Core文件(3)
    • 前言
    • 1、C++生成Core和使用GDB调试
      • 1、环境
      • 2、C++生成Core文件
      • 3、使用gdb工具调试core可定位段错误位置;
      • 4、修改生成的Core文件路径和名称
      • 5、实现过程及结果
    • 2、Qt程序生成Core和使用GDB调试
      • 1、环境
      • 2、Qt生成Core文件
      • 3、调试Qt程序生成的Core文件
      • 4、Qt在Release模式下调试Core文件

更多精彩内容
👉个人内容分类汇总 👈
👉C++软件调试、异常定位 👈

Windows下封装的崩溃报告模块

前言

  • 什么是Core文件,有什么用

    Core文件是在程序崩溃或异常终止时由操作系统生成的一个二进制文件,它包含了进程在崩溃前的内存映像。Core文件的作用是帮助程序员分析程序崩溃的原因,进行程序调试。

    当程序崩溃时,Core文件中存储了进程的堆栈、寄存器、内存等信息。程序员可以使用调试工具如GDB来分析Core文件,以确定程序崩溃的原因。通过分析Core文件,程序员可以了解程序在崩溃前发生的情况,包括变量的值,函数调用的堆栈信息等,从而找到程序中的错误。

    Core文件还可用于恢复程序状态。如果程序在处理大量数据时崩溃,程序员可以使用Core文件来恢复程序状态,从崩溃点开始进行调试,以便更快地找到问题并修复它。

    总之,Core文件是程序调试和故障排除中的重要工具,可以帮助程序员快速定位并解决程序中的错误。

1、C++生成Core和使用GDB调试

1、环境

  • 测试系统:

    • ubuntu-16.04.6-desktop-i386.iso
    • ubuntu-22.04.2-desktop-amd64.iso
  • 为了排除其它影响,每个测试的系统环境都是在虚拟机中新配置的纯净环境,没有安装任何其它软件和进行任何配置。

2、C++生成Core文件

  1. 创建一个文件夹Code

    mkdir Code
    
  2. 进入Code文件夹,创建一个main.cpp文件

    cd Code
    touch main.cpp
    
  3. 打开main.cpp,写入下列代码

    touch main.cpp 
    
    #include <stdio.h>
    
    int main()
    {
        char* str = NULL;
        *str = 'a';
        return 0;
    }
    
  4. 在ubuntu环境下,默认不生成core文件,需要生成core文件时,需要使用ulimit进行设定;

    注意: 此命令设置的core文件大小只在当前终端,当前用户有效,重新打开一个终端窗口或者切换用户就会失效;

    在这里插入图片描述

    ulimit-c”命令设置或获取core文件大小限制,该限制指定进程崩溃时可以创建的核心转储文件的最大大小。

    核心转储文件包含崩溃时进程内存的映像,这对于调试崩溃原因非常有用。

    “-c”选项以块或字节为单位指定核心文件大小限制,具体取决于系统配置。

    # 列出当前终端所有资源限制
    ulimit -a 
    
    # core文件大小
    ulimit -c
    
    # 设置生成core文件的大小:1024k
    ulimit -c 1024
    
    # 设置生成core文件的大小:不受限制(推荐使用这个,因为如果是Qt之类的程序生成的Core文件会很大,如果指定的大小不够则可能生成的Core文件无法使用)
    ulimit -c unlimited
    

    在这里插入图片描述

  5. 如果您想让 ‘ulimit -c unlimited’ 命令永久生效,您需要在系统启动时将其添加到 shell 配置文件中。具体的配置文件路径可能会因操作系统而异,一些常见的配置文件路径如下:

   - /etc/profile (适用于所有用户)
   - ~/.bashrc (适用于当前用户)
   - /etc/bashrc (适用于所有用户)

您可以使用文本编辑器打开适当的文件,并将 ‘ulimit -c unlimited’ 命令添加到文件的末尾。

保存文件后,使用source .bashrc命令立即生效或者下次启动系统时,该命令将自动执行并永久生效。

但是永久生效就意味着系统中只要由程序异常结束就会生成Core文件,这会导致系统中垃圾文件越来越多,所以除非必要,还是使用临时设置。

如果设置了永久生效,建议将指定生成Core路径时使用绝对路径,将所有生成的Core文件放到同一个文件夹下,方便管理。

  1. 编译main.cpp文件,用-g选项生成的调试信息来显示崩溃或错误时的源代码、变量和堆栈跟踪;

    g++ main -g
    
  2. 使用./a.out命令执行编译后的可执行程序,会出现段错误segmentation fault (core dumped),并在当前路径生成core文件;

    在这里插入图片描述

3、使用gdb工具调试core可定位段错误位置;

命令为 gdb 可执行程序 Core文件

如下图所示可看出段错误为main.cpp文件中main()函数中,位于文件第6行;

在这里插入图片描述

在这里插入图片描述

4、修改生成的Core文件路径和名称

core_pattern文件是一个系统文件,用来指定生成Core文件的路径和文件名格式。可以通过修改core_pattern文件来更改Core文件的生成路径和文件名格式。

【临时设置(立即生效)】在Linux系统中,core_pattern文件通常位于/proc/sys/kernel/core_pattern路径下。可以使用命令行编辑器如vi或nano来编辑该文件。

需要注意的是,core_pattern文件是一个虚拟文件,它是在内存中创建的,并不是一个真正的文件。因此,修改core_pattern文件的设置选项只在当前系统运行时有效,重启系统后设置会被恢复为默认值

【永久设置(需要重启)】如果要永久更改设置选项,可以在系统启动时执行相应的命令,或者修改 /etc/sysctl.conf 文件中的相应设置选项。

可以到/etc/sysctl.conf中,在文件末尾添加上core文件的存储路径(然后重启系统):

kernel.core_pattern=core_%e_%p_%t
  1. 默认生成的Core文件名就是Core,所以后面生成的会覆盖之前生成的文件,如果想要不覆盖可用自己修改生成的文件名;

  2. 进入root用户模式;

    sudo su
    
  3. 查看/proc/sys/kernel/core_pattern文件原始配置;

    cat /proc/sys/kernel/core_pattern
    或者
    sysctl kernel.core_pattern
    
  4. 修改/proc/sys/kernel/core_pattern文件中Core生成路径、文件名配置;

    # 表示在可执行程序当前路径生成Core文件,文件名格式为core_%e_%p_%t
    echo "core_%e_%p_%t" > /proc/sys/kernel/core_pattern
    或者
    sudo sysctl -w kernel.core_pattern="core_%e_%p_%t"
    
    # 表示在可执行程序当前路径下的Cores文件夹中(需要自己手动创建Cores文件夹)生成Core文件,文件名格式为core_%e_%p_%t
    echo "./Cores/core_%e_%p_%t" > /proc/sys/kernel/core_pattern
    
    # 表示在绝对路径/home/mhf/Cores/中(需要自己手动创建Cores文件夹)生成Core文件,文件名格式为core_%e_%p_%t
    echo "/home/mhf/Cores/core_%e_%p_%t" > /proc/sys/kernel/core_pattern
    

    如果不包含路径,则core_pattern文件中的内容为【在执行文件当前路径】创建相应的core文件;

    如果包含路径,则需要保证路径存在,否则不会生成Core文件;

    注意:如果生成的路径的权限比较高,也不会生成Core文件,例如:

    # 表示在绝对路径/Cores/中(需要自己手动创建Cores文件夹)生成Core文件,文件名格式为core_%e_%p_%t
    # /Cores路径需要root权限,如果使用普通用户权限执行a.out则不会生成Core文件,需要使用sudo ./a.out执行才可以生成
    echo "/Cores/core_%e_%p_%t" > /proc/sys/kernel/core_pattern
    

    其中可选参数列表为:

    %p:将进程ID(PID)插入文件名
    %u:将进程的真实用户ID(RUID)插入文件名
    %g:将进程的真实组ID(RGID)插入文件名
    %s:将生成Core文件时,进程的信号编号插入文件名
    %t:将内核转储发生的UNIX时间戳(秒级)插入文件名
    %h:将主机名插入文件名
    %e:将核心转储可执行文件名插入文件名

5、实现过程及结果

  • 显示(core dumped)表示成功生成Core文件。
  • ubuntu16.04使用过程及结果如下

在这里插入图片描述

  • ubuntu22.04使用过程及结果如下

在这里插入图片描述

2、Qt程序生成Core和使用GDB调试

1、环境

  • 系统:ubuntu22.04
  • Qt版本:V5.14.2

2、Qt生成Core文件

  1. 打开一个终端,如下图所示,将生成的Core文件大小设置位为不限制,设置core生成文件名称,防止覆盖;

  2. 由于这两项设置是临时的,重新打开一个终端窗口或者通过点击图标方式运行Qt都无效,只能在当前终端窗口通过命令行运行Qt编译的可执行程序在异常时才可以生成Core文件;

  3. 如果是通过点击图标运行的Qt编译生成的可执行程序,需要在当前终端窗口通过命令行运行可执行程序才可以生成core文件;

    在这里插入图片描述

  4. Qt程序启动后新建一个工程;

  5. 在pro文件添加DESTDIR = $$PWD/bin,将编译后的可执行程序放到bin文件夹下;

  6. 在代码中编写一个空指针异常代码、一个除0异常代码;

  7. 使用debug编译运行后,分别点击空指针异常代码和除0异常代码的按键;

    在这里插入图片描述

  8. 在点击异常代码的按键后,程序会异常退出,在可执行程序所在的bin文件夹下可看到生成了两个Core文件;

    在这里插入图片描述

  9. 从下图中可看出生成的两个core文件非常大,所以:

    1. 最好使用ulimit -c unlimited指定无限大小的Core,否则生成的Core大小不足,则无法使用;
    2. 没必要时必要将ulimit -c unlimited设置为永久有效,否则系统可能中会生成非常多的core文件,导致内存不足。

    在这里插入图片描述

3、调试Qt程序生成的Core文件

  1. 在上一节中使用C++生成的Core文件我们通过GDB命令行去调试,定位异常位置;

  2. 这里同样使用GDB命令行进行调试;

    1. 可用看出异常位置在../untitled/widget.cpp文件中的第29行,位于Widget::on_pushButton_2_clicked()函数中;
    2. 异常原因是:Arithmetic exception.

    在这里插入图片描述

  3. 同样使用GDB命令行调试空指针生成的core文件

    1. 只能看出异常原因是Segmentation fault.(段错误),无法直接看出是异常发生位置是在哪个文件,哪一行,哪个函数;
    2. 先不用急, 后面我会将如何使用QtCreator调试生成的Core文件,会更加简单方便,并且也可以直接显示出异常位置是在哪个文件,哪一行,哪个函数;

    在这里插入图片描述

    1. 这里看不到异常位置可能是不在这个堆栈内,可以使用bt命令打印函数调用信息(堆栈);

      1. 可以看到定位异常在widget.cpp文件中的21行的Widget::on_pushButton_clicked()函数内;

      在这里插入图片描述

4、Qt在Release模式下调试Core文件

  1. 在debug和Release编译的程序发生异常退出时都会生成Core文件,但是release模式默认下生成的可执行程序经过编译器优化,不方便调试和定位异常位置;

  2. 使用Release默认生成的可执行程序进行调试结果如下,通过GDB的bt命令打印堆栈信息可以看出异常位置在Widget::on_pushButton_clicked() 函数中,没有具体到哪个文件,哪一行;

    在这里插入图片描述

  3. Release模式下,可用通过在pro文件添加下列三行代码关闭打印输出的信息,经过测试,如果添加了DEFINES += QT_NO_DEBUG_OUTPUT则无法定位异常位置(Debug模式不影响);

    DEFINES += QT_NO_DEBUG_OUTPUT    # 关闭调试信息输出 qDebug()    ---  无法定位异常位置
    DEFINES += QT_NO_INFO_OUTPUT     # 关闭普通信息输出 qInfo()     ---  不影响
    DEFINES += QT_NO_WARNING_OUTPUT  # 关闭警告信息输出 qWarning()  ---  不印象
    

    在这里插入图片描述

  4. Release模式下,在pro文件添加下列三行代码,生成调试信息,可定位到异常位置在哪个文件,哪个函数,哪一行;

    # QMAKE_CC += -g是一个QMake变量,它将-g选项添加到C编译器命令行选项中。-g选项指示编译器生成调试信息以及目标代码。
    # 调试信息包含有关源代码的详细信息,例如文件名、行号和变量名。在调试程序时,这些信息对开发人员非常有用,因为它们可以跟踪程序的执行并识别错误的位置。
    # 请注意,添加-g标志会增加目标文件和可执行文件的大小,因此不希望在程序的最终发布版本中包含调试信息。
    QMAKE_CC += -g
    # QMAKE_CXX += -g是一个QMake变量,它将-g选项添加到C++编译器命令行选项中。-g选项指示编译器生成调试信息以及目标代码。
    QMAKE_CXX += -g
    # QMAKE_LINK += -g是一个QMake变量,它将-g选项添加到链接器命令行选项中。-g选项指示链接器将调试信息包含在可执行文件中。
    QMAKE_LINK += -g
    

    在这里插入图片描述

  5. Release模式下同时添加-gDEFINES += QT_NO_DEBUG_OUTPUT可定位到异常位置在哪个文件,哪个函数,哪一行;

  6. 只需要在pro文件中加上下列三行代码,就可以在生成的可执行程序中包含调试信息;

    • 其实感觉这个功能比较鸡肋,Debug编译的程序就已经带有了调试信息,所以如果调试问题最好使用Debug模式编译,而Release是编译发布程序的模式,经过优化后去除调试信息,以获得更高的性能和较小的程序文件;
    • 而加上这三行代码后在可执行程序中包含调试信息,哪就和Debug没什么区别了,性能比较低了;
    • 当然,有些问题会在Release模式下出现,在Debug模式下不会出现,这种情况就可以使用这三行代码。
    # QMAKE_CC += -g是一个QMake变量,它将-g选项添加到C编译器命令行选项中。-g选项指示编译器生成调试信息以及目标代码。
    # 调试信息包含有关源代码的详细信息,例如文件名、行号和变量名。在调试程序时,这些信息对开发人员非常有用,因为它们可以跟踪程序的执行并识别错误的位置。
    # 请注意,添加-g标志会增加目标文件和可执行文件的大小,因此不希望在程序的最终发布版本中包含调试信息。
    QMAKE_CC += -g
    # QMAKE_CXX += -g是一个QMake变量,它将-g选项添加到C++编译器命令行选项中。-g选项指示编译器生成调试信息以及目标代码。
    QMAKE_CXX += -g
    # QMAKE_LINK += -g是一个QMake变量,它将-g选项添加到链接器命令行选项中。-g选项指示链接器将调试信息包含在可执行文件中。
    QMAKE_LINK += -g
    
  7. 从下图可以看出所有模式生成的Core文件大小都一样,但是Debug模式编译生成的可执行程序是Release模式编译的可执行程序的大小的31倍左右,而Release模式加-g后编译生成的可执行程序大小和Debug模式生成的大小差不多。

    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【创作赢红包】你是真的“C”——C语言中文件操作函数使用的详细讲解【上篇】

你是真的“c”——C语言中文件操作函数使用的详细讲解~&#x1f60e;前言&#x1f64c;一、 为什么使用文件&#xff1a;&#x1f64c;二、 什么是文件&#xff1a;&#x1f64c;2.1 程序文件2.2 数据文件2.3 文件名3. 文件的打开和关闭3.1 文件指针3.2 文件的打开和关闭4. 文件…

【ansible】实施任务控制

目录 实施任务控制 一&#xff0c;循环&#xff08;迭代&#xff09;--- loop 1&#xff0c;利用loop----item循环迭代任务 2&#xff0c;item---loop循环案例 1&#xff0c;定义item循环列表 2&#xff0c;通过变量应用列表格式 3&#xff0c;字典列表&#xff08;迭代嵌套子…

一个ESP32小东西

之前发了ESP8266&#xff0c;有人评论说玩下ESP32然后就买了几个回来&#xff0c;当然&#xff0c;也想着和大家一起玩介绍下这个开发板开发板Github项目链接https://github.com/Xinyuan-LilyGO/T-QT把仓库的代码下载到本地我们可以用ESP-IDF和Arduino两个SDK来开发ESP32S3ESP-…

回溯算法思想、回溯算法解题模板与回溯算法题目索引(不断更新)

回溯算法 回溯算法是一种试探性的搜索算法&#xff0c;它在解决某些组合问题、优化问题、路径问题等&#xff0c;非常有效。回溯算法的核心思想是通过递归和深度优先搜索&#xff08;DFS&#xff09;来搜索问题的解空间。 细说一下这些问题&#xff1a; 组合问题&#xff1a;N…

初级网络工程师这30道面试题一定得会,建议小白收藏!

你好&#xff0c;这里是网络技术联盟站。 后台有小伙伴想让瑞哥整理一下初级网络工程师面试题&#xff0c;今天我整理出来了&#xff0c;针对初级网络工程师&#xff0c;我们在面试的时候主要考察的是基础概念&#xff0c;下面列举的希望大家可以收藏&#xff0c;平时多看看&a…

活动选择问题 | 贪心算法 1

贪心法是一种算法范式&#xff0c;它逐个构建解决方案&#xff0c;始终选择下一个提供最明显和最直接好处的部分。贪心算法用于优化问题。 如果问题具有以下属性&#xff0c;则可以使用 Greedy 解决优化问题&#xff1a; 在每一步中&#xff0c;我们都可以做出当前看起来最好…

MongoDB 6.0 (四)聚合操作

一、 聚合框架的作用 1. 什么是MongoDB 聚合框架 MongoDB 聚合框架(Aggregation Framework)是一个计算框架,它可以: • 作用在一个或几个集合上; • 对集合中的数据进行的一系列运算; • 将这些数据转化为期望的形式; 从效果而言,聚合框架相当于SQL 查询中的: …

【Mysql系列】——详细剖析数据库“索引”【上篇】

【Mysql系列】——详细剖析数据库中的核心知识【索引】&#x1f60e;前言&#x1f64c;索引索引概述为什么需要索引&#xff1f;索引的优缺点索引结构索引的结构为什么不是二叉树和红黑树&#xff1f;索引的B树结构索引的Hash结构Hash结构索引的特点思考&#xff1a;为什么Inno…

MySQL中多表查询(多表关系:一对多、多对多、一对一,分类:连接查询:内连接、外连接、自连接、联合查询,子查询:标量子查询、列子查询、行子查询、表子查询)

多表关系&#xff1a; 一对多&#xff1a; 多对多&#xff1a; 一对一&#xff1a; 我们发现我们利用DQL中的select语句查询多张表的时候&#xff0c;会出现一个数学现象&#xff0c;叫做笛卡尔积 因此我们可以加上where语句来限定条件&#xff1a; 内连接&#xff1a; 此处in…

计算机网络面试八股文攻略(一) —— OSI 七层模型

一、简述 本系列将对面试中与计算机网络相关的知识进行讲解与分析。 本篇为 OSI 七层网络模型的相关知识。 二、概念 OSI 七层网络模型是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联的标准体系。它是一个七层的、抽象的模型体&#xff…

A Causal Debiasing Framework for Unsupervised Salient Object Detection

背景知识 显著性检测 简单就是使用图像处理技术和计算机视觉算法来定位图片中最“显著”的区域。显著区域就是指图片中引人注目的区域或比较重要的区域&#xff0c;例如人眼在观看一幅图片时会首先关注的区域。 chatGPT4的回答 计算机视觉中的显著性检测&#xff08;Visual…

从事6个月软件测试,目前只会功能测试迷茫了...

前言 (来自一位粉丝的投稿)来这个公司大半年&#xff0c;现在主要做的是类似于淘宝的购物商城&#xff0c;以前也做应用系统什么的&#xff0c;可是感觉公司的软件测试岗位都是不着边的&#xff0c;因为做的都是功能测试&#xff0c;来了这么久&#xff0c;没接触过技术性的东…

美丽苏大,清华博士,年轻硕导,招收研究生了!

Datawhale学术 导师&#xff1a;张正超&#xff0c;苏州大学&#xff0c;Datawhale成员导师信息本人于2022年取得清华大学博士学位&#xff0c;目前是苏州大学计算机科学与技术学院的硕士生导师&#xff0c;2023年可招收计算机科学与技术、软件工程、人工智能及大数据技术与工程…

微服务保护Sentinel一站式学习

微服务保护Sentinel 雪崩问题 解决雪崩问题的四种常见方式&#xff1a; 超时处理&#xff1a;设定超时时间&#xff0c;请求超过一定时间没有响应就返回错误信息&#xff0c;不会无休止等待。如果设置一秒钟没响应返回&#xff0c;即1s释放连接&#xff0c;这1s中有好多个请求…

BOSS直拒、失联招聘,消失的“金三银四”,失业的测试人出路在哪里?

裁员潮涌&#xff0c;经济严冬。最近很多测试人过得并不好&#xff0c;行业缩水对测试岗位影响很直接干脆&#xff0c;究其原因还是测试门槛在IT行业较低&#xff0c;同质化测试人员比较多。但实际上成为一位好测试却有着较高的门槛&#xff0c;一名优秀的测试应当对产品的深层…

Stable Diffusion 视频和图片帧互换以及AI动画帧生成

Stable Diffusion 只做AI动画是基于把原有视频按照帧进行提取之后对每一帧的图像进行标准化流程操作&#xff0c;中间可以掺杂Controlnet对人物进行控制&#xff0c;使用关键词对画面进行控制&#xff0c;但是很多小伙伴不太会掌握一些编辑视频软件或者python的操作导致视频转帧…

Java 深入理解Servlet

动态资源与静态资源区别 servlet三及相关接口简介servet 执行过程servlet路径映射servlet生命周期(重点) --理解&#xff08;重点&#xff09;Servlet自动加载Servlet线程安全Servlet相关接口详解ServletContext对象 --知识点 一、Web项目结构 |- WebRoot : web应用的根目录…

【linux】常用命令大全(入门必备)

这篇文章涵盖了linux中常用的所有指令&#xff0c;欢迎大家阅读查询。(如有不正确的地方&#xff0c;各位大佬可以在评论区指出&#xff0c;我会及时进行更正)。 文章目录登录远程服务器ssh添加删除用户当前路径pwd列出文件目录ls进入cdtreewhoami创建文件touch创建目录mkdir删…

【C语言学习】循环结构和选择结构

C语言中有三大结构&#xff0c;分别是顺序结构、选择结构和循环结构&#xff08;分支结构&#xff09;&#xff1a; C语言顺序结构就是让程序按照从头到尾的顺序依次执行每一条C语言代码&#xff0c;不重复执行任何代码&#xff0c;也不跳过任何代码。 C语言选择结构也称分支结…

都说IT行业饱和了,2023年成为程序员还有发展前景吗?

程序员饱和了吗&#xff1f;初级码农肯定是算饱和了&#xff0c;因为大部分的互联网企业开始提高招聘要求了&#xff0c;比如技能要求、两三年工作经验、项目经验、软实力等&#xff0c;是按照中级开发人员的标准来的。所以干程序员还是有发展前景的&#xff0c;你的技能达标了…
最新文章