【Qt】为程序增加闪退crash报告日志

背景

随着软件代码量的增加,软件崩溃闪退的肯能行越来越大,其中一些是难以复现的,比如访问了访问了非法地址、被操作系统杀死等。

为此,在软件出现闪退情况时,尽可能多的记录闪退发生时信息,对排查闪退原因是非常有帮助的。

实现

因为闪退发生时软件已经不在运行了,因此需要在闪退前就告诉操作系统闪退后需要执行的操作,在Qt中就是在QApplicationexec()前调用操作系统提供的接口,注册闪退后的处理函数。

我们以Windows平台为例,在Windows平台,时利用SetUnhandledExceptionFilter函数实现异常(闪退)处理函数的注册的。

简单代码如下:

#include <QApplication>#ifdef Q_OS_WIN
#include <windows.h>
#include <psapi.h>
#include <DbgHelp.h>
#include <fstream>
#include <sstream>#pragma comment(lib, "DbgHelp.lib")
LONG WINAPI windowsCrashHandler(EXCEPTION_POINTERS* ex) {SYSTEMTIME time;GetLocalTime(&time);char logName[256];// 文件名格式crash_yyyymmdd_hhmmss.logsprintf(logName, "crash_%04d%02d%02d_%02d%02d%02d.log",time.wYear, time.wMonth, time.wDay,time.wHour, time.wMinute, time.wSecond);// 打开日志文件std::ofstream logFile(logName);if (!logFile.is_open()) return EXCEPTION_EXECUTE_HANDLER;// 记录异常信息logFile << "=== Exception: "<< ex->ExceptionRecord->ExceptionCode<<" ==="<< std::endl;// 记录内存占用(Windows)MEMORYSTATUSEX statex;statex.dwLength = sizeof(statex);if (GlobalMemoryStatusEx(&statex)) {logFile << "总内存:" << statex.ullTotalPhys / (1024 * 1024) << " MB" << std::endl;}PROCESS_MEMORY_COUNTERS pmc;GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));logFile << "内存占用: "<< pmc.WorkingSetSize / (1024 * 1024)<< " MB" << std::endl;logFile << "Error Code: 0x" << std::hex << ex->ExceptionRecord->ExceptionCode << std::endl;// 获取调用堆栈HANDLE process = GetCurrentProcess();HANDLE thread = GetCurrentThread();SymInitialize(process, NULL, TRUE);  // 初始化符号表// 遍历堆栈帧STACKFRAME64 stackFrame = {{0}};stackFrame.AddrPC.Offset = ex->ContextRecord->Rip;  // x86 用 Eip, x64 用 RipstackFrame.AddrPC.Mode = AddrModeFlat;stackFrame.AddrStack.Offset = ex->ContextRecord->Rsp;  // x86 用 Esp, x64 用 RspstackFrame.AddrStack.Mode = AddrModeFlat;stackFrame.AddrFrame.Offset = ex->ContextRecord->Rbp;  // x86 用 Ebp, x64 用 RbpstackFrame.AddrFrame.Mode = AddrModeFlat;DWORD imageType;
#ifdef _M_IX86imageType = IMAGE_FILE_MACHINE_I386;
#elif _M_X64imageType = IMAGE_FILE_MACHINE_AMD64;
#endiflogFile << "调用堆栈:" << std::endl;int frameNum = 0;while (StackWalk64(imageType, process, thread, &stackFrame, ex->ContextRecord,NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {// 获取符号信息BYTE symbolBuffer[sizeof(SYMBOL_INFO) + 256] = {0};SYMBOL_INFO* symbol = (SYMBOL_INFO*)symbolBuffer;symbol->SizeOfStruct = sizeof(SYMBOL_INFO);symbol->MaxNameLen = 255;DWORD64 displacement = 0;if (SymFromAddr(process, stackFrame.AddrPC.Offset, &displacement, symbol)) {logFile << "[" << frameNum << "] " << symbol->Name << std::endl;} else {logFile << "[" << frameNum << "] Unknown Address" << std::endl;}frameNum++;}// 清理符号表SymCleanup(process);logFile.close();// 退出程序return EXCEPTION_EXECUTE_HANDLER;
}
#endifint main(int argc, char *argv[])
{#ifdef Q_OS_WIN// Windows 注册异常(闪退)处理函数SetUnhandledExceptionFilter(windowsCrashHandler);
#endifQApplication a(argc, argv);return a.exec();
}

这样在程序出现闪退后,就可以看到闪退时计算机内存的占用情况以及引起闪退的调用堆栈。

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

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

相关文章

C#从入门到精通(35)—如何防止winform程序因为误操作被关闭

前言: 大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在开发的上位机软件运行起来以后,一般在右上角都有一个关闭按钮,正常情况下点击关闭按钮就能关闭软件,但是不排除我们不想关闭软件,但是因为不…

ffmpeg avdevice_register_all 注册设备的作用

在 FFmpeg 中&#xff0c;avdevice_register_all() 是一个用于注册所有输入和输出设备的函数。它是 FFmpeg 的 libavdevice 模块的一部分&#xff0c;专门用于处理音频和视频的输入/输出设备&#xff08;如摄像头、麦克风、屏幕捕获等&#xff09;。 以下是对 avdevice_regist…

[RH342]tcpdump

[RH342]tcpdump 1. 题目2. 解题 1. 题目 服务器serverc 和 servera 之间有进程定期发送一个明文密码,找出它2. 解题 找出通信端口 抓包分析 tcpdump -X -vv port 6644红框中就是密码,所以密码是root123

连接Sql Server时报错无法通过使用安全套接字层加密与 SQL Server 建立安全连接

文章目录 一. 前言二. 解决方案 方案1方案2 三. 总结 一. 前言 在《数据库原理》这门课的实验上&#xff0c;需要使用SQL Server&#xff0c;然后使用jdbc连接sql server突然报错为&#xff1a;SQLServerException: “Encrypt”属性设置为“true”且 “trustServerCertific…

从 Spring Boot 2 升级到 Spring Boot 3 的终极指南

一、升级前的核心准备 1. JDK 版本升级 Spring Boot 3 强制要求 Java 17 及以上版本。若当前项目使用 Java 8 或 11&#xff0c;需按以下步骤操作&#xff1a; 安装 JDK 17&#xff1a;从 Oracle 或 OpenJDK 官网下载&#xff0c;配置环境变量&#xff08;如 JAVA_HOME&…

Buildroot 添加自定义模块-内置文件到文件系统

目录 概述实现步骤1. 创建包目录和文件结构2. 配置 Config.in3. 定义 cp_bin_files.mk4. 添加源文件install.shmy.conf 5. 配置与编译 概述 Buildroot 是一个高度可定制和模块化的嵌入式 Linux 构建系统&#xff0c;适用于从简单到复杂的各种嵌入式项目. buildroot的源码中bui…

物联网通信应用案例之《智慧农业》

案例概述 在智慧农业方面&#xff0c;一般的应用场景为可以自动检测温度湿度等一系列环境情况并且可以自动做出相应的处理措施如简单的浇水和温度控制等&#xff0c;且数据情况可远程查看&#xff0c;以及用户可以实现远程控制。 基本实现原理 传感器通过串口将数据传递到Wi…

设计模式| 观察者模式 Observer Pattern详解

目录 一、概述1.1 动机1.2 核心思想1.3 别名 二、角色与实现原理2.1 角色2.2 实现原理2.3 类图 三、经典接口实现3.1 示例3.1.1 观察者接口3.1.2 目标接口3.1.3 具体被观察者3.1.4 具体观察者3.1.5 Client3.1.6 UML时序图 3.2 特点 四、其他实现方式4.1 委托与事件&#xff08;…

kotlin 知识点一 变量和函数

在Kotlin中定义变量的方式和Java 区别很大&#xff0c;在Java 中如果想要定义一个变 量&#xff0c;需要在变量前面声明这个变量的类型&#xff0c;比如说int a表示a是一个整型变量&#xff0c;String b表 示b是一个字符串变量。而Kotlin中定义一个变量&#xff0c;只允许在变量…

基于数据可视化学习的卡路里消耗预测分析

数据分析实操集合&#xff1a; 1、关于房间传感器监测数据集的探索 2、EEMD-LSTM模型择时策略 — 1.EEMD分解与LSTM模型搭建 3、EEMD-LSTM模型择时策略 — 2. 量化回测 4、国际超市电商销售数据分析 5、基于问卷调查数据的多元统计数据分析与预测&#xff08;因子分析、对应分…

记录Liunx安装Jenkins时的Package ‘jenkins‘ has no installation candidate

1、确保是否安装了Java&#xff0c;如果没有&#xff0c;可通过以下命令进行安装&#xff1a; sudo apt update sudo apt install openjdk-21-jre2、安装Jenkins sudo apt update sudo apt install jenkins执行sudo apt install jenkins时&#xff0c;可能会出现 意思是&…

kiln微调大模型-使用deepseek R1去训练一个你的具备推理能力的chatGPT 4o

前言 随着deepseek的爆火&#xff0c;对于LLM的各种内容也逐渐步入我的视野&#xff0c;我个人认为&#xff0c;可能未来很长一段时间&#xff0c;AI将持续爆火&#xff0c;进入一段时间的井喷期&#xff0c;AI也会慢慢的走入我们每个家庭之中&#xff0c;为我们的生活提供便利…

用AI玩游戏1——狼人杀六人局

狼人杀六人局1 狼人杀六人局1&#xff0c;好人阵营有两个平民&#xff0c;一个预言家&#xff0c;一个守卫&#xff0c;坏人阵营有两个狼人。狼人每晚可以选择杀死一个人但第一天晚上不能杀人&#xff0c;狼人晚上可以睁眼识别到同伴和其他好人玩家但不知道他们的身份。预言家…

sqli-labs

Less-8 单引号报错&#xff0c;双引号显示正常 又是You are in......看来还是用盲注 布尔盲注&#xff1a; 如下语句是用来判断当前数据库名的第一个字母是不是s&#xff0c;后面的以此类推&#xff0c;比较复杂和麻烦 ?id1 and substr(database(),1,1)s -- 比如这个我们通…

自定义ToolbarView实战指南(Kotlin版)

一、为什么我们需要造轮子&#xff1f; 看到标题你可能会问&#xff1a;系统自带Toolbar不香吗&#xff1f;确实香&#xff0c;但遇到这些场景就抓瞎了&#xff1a; 设计稿要求标题栏带渐变背景动态波浪线产品经理非要搞个不对称的返回按钮布局UI设计师坚持标题和副标题要45度…

微软推出Office免费版,限制诸多,只能编辑不能保存到本地

易采游戏网2月25日独家消息&#xff1a;微软宣布推出一款免费的Office版本&#xff0c;允许用户进行基础文档编辑操作&#xff0c;但限制颇多&#xff0c;其中最引人关注的是用户无法将文件保存到本地。这一举措引发了广泛讨论&#xff0c;业界人士对其背后的商业策略和用户体验…

PyTorch-基础(CUDA、Dataset、transforms、卷积神经网络、VGG16)

PyTorch-基础 环境准备 CUDA Toolkit安装&#xff08;核显跳过此步骤&#xff09; CUDA Toolkit是NVIDIA的开发工具&#xff0c;里面提供了各种工具、如编译器、调试器和库 首先通过NVIDIA控制面板查看本机显卡驱动对应的CUDA版本&#xff0c;如何去下载对应版本的Toolkit工…

Vue2+Element实现Excel文件上传下载预览【超详细图解】

目录 一、需求背景 二、落地实现 1.文件上传 图片示例 HTML代码 业务代码 2.文件下载 图片示例 方式一&#xff1a;代码 方式二&#xff1a;代码 3.文件预览 图片示例 方式一&#xff1a;代码 方式二&#xff1a;代码 一、需求背景 在一个愉快的年后&#xff…

【Bug】natten:安装报错(临近注意力机制的高效cuda内核实现)

正常安装natten报错 pip install natten 报错 可以尝试使用以下网站进行安装 https://shi-labs.com/natten/ 可以根据自己的cuda与pytorch版本进行安装 之间复制命令即可&#xff0c;不需要进行任何修改

win10把c盘docker虚拟硬盘映射迁移到别的磁盘

c盘空间本身就比较小、如果安装了docker服务后&#xff0c;安装的时候没选择其他硬盘&#xff0c;虚拟磁盘也在c盘会占用很大的空间&#xff0c;像我的就三十多个G&#xff0c;把它迁移到其他磁盘一下子节约几十G 1、先输入下面命令查看 docker 状态 wsl -l -v 2、如果没有停止…