Windows下定位Mingw编译的Qt程序崩溃堆栈

一、dump和pdb是什么

        在Windows系统下,当我们写的程序跑在客户的机器上,因为一个bug,导致程序崩溃,我们该如何定位并修复这个bug呢?

        有人会说记录日志,即便有日志,也是不好定位的,因为你只能推测出大概的模块或者位置,无法定位到具体出错的代码行。

        此时,我们可以让程序崩溃后,自动生成一个*.dmp文件,并配合在编译该程序时生成的pdb文件,来准确定位到调用堆栈、代码行上。这样很轻易就可以找到该bug。

  • dump文件,后缀*.dmp,是程序崩溃时的内存转储文件;

  • pdb文件,后缀*.pdb,是程序的符号文件。

二、Breakpad与qbreakpad简介

        Breakpad是由Google开发的开源跨平台崩溃报告系统,用于捕获程序崩溃时的内存状态并生成轻量级minidump文件(.dmp)。其核心功能包括崩溃拦截、堆栈记录和寄存器状态捕获,适用于C++应用的多平台部署(Windows/Linux/macOS)‌。

        QBreakpad是Breakpad的‌Qt专用封装库‌,它将Breakpad的复杂集成简化为Qt模块,提供更便捷的API和跨平台兼容性,专门服务于Qt应用程序的崩溃管理‌。

        BreakPad工作原理示意图:

表达的意思就是:

  • 我们在编译的时候,需要在Release版程序中生成调试信息。

  • 使用Breakpad提供的dump_syms工具或者cv2pdb工具,从release版本程序导出符号文件。

  • 当程序崩溃时,breakpad会捕捉崩溃,并生成dump文件。

  • dump文件可以直接发送到指定服务器,或者由用户手动发给开发者。

  • 收到dump文件后,结合符号文件,可通过minidump_stackwalk工具或Visual Studio工具生成堆栈调用信息文件,这个文件可以直接阅读,定位bug。

三、开发环境说明

        本人使用的开发环境如下:

        操作系统:Windows10

        IDE:Qt Creator4.4.1

        编译器:mingw53_32

        Qt库:Qt5.9.3 

四、源码准备

        我们知道qBreakpad是对Breakpad的封装,所以qBreakpad的编译,还依赖2套源码Breakpad、LSS。

(1)下载Breakpad源码

下载地址:https://github.com/google/breakpad

(2)下载LSS源码

下载地址:https://github.com/ithaibo/linux-syscall-support

(3)下载qBreakpad源码

下载地址:https://github.com/buzzySmile/qBreakpad

 (4)下载cv2pdb工具

下载地址:

注意:这个工具最好下载最新版本的,作者发布本文时,最新版本是cv2pdb 0.53

五、编译qBreakpad

(1)将Breakpad、LSS源码放入third_party目录

        解压qBreakpad源码后,在qBreakpad-master\third_party目录下,有如下2个目录,如下:

        分别解压Breakpad、LSS源码至breakpad和lss目录,此2个目录下源码需要参与qBreakpad的编译。放置好后,如下所示:

(2)qBreakpad工程介绍

        在qBreakpad源码目录下,使用QtCreator打开qBreakpad.pro工程,如下:

  • demo工程下,有2个演示程序program和reporter,分别实现了演示生成dump文件,上报dump文件的功能。

  • handler为静态库工程,该工程封装了Breakpad,直接编译此工程,可生成qBreakpad.lib。

  • tests为一个简单的测试工程。

(3)编译生成qBreakpad.lib

        分别在Debug、Release模式下,编译handler工程,生成2个版本的qBreakpad.lib静态库。

因为程序调用qBreakpad.lib时,只能debug版程序链接debug版库,release版程序链接release版库。debug版程序链接release版库会报错。

(4)编译生成demo

      在program.pro文件添加下图所示内容,目的是编译release版程序时生成调试信息:

############ for qBreakpad ############
# qBreakpad中需要使用到network模块
QT += network# 启用多线程、异常、RTTI、STL支持
CONFIG += thread exceptions rtti stl# without c++11 & AppKit library compiler can't solve address for symbols
CONFIG += c++11
macx: LIBS += -framework AppKit# 启用调试信息(关键!)
QMAKE_CXXFLAGS += -g
QMAKE_CXXFLAGS_RELEASE += -g
QMAKE_CFLAGS_RELEASE += -g
#release在最后link时默认有"-s”参数,表示"Omit all symbol information from the output file",因此要去掉该参数
QMAKE_LFLAGS_RELEASE = -mthreads -Wl,# 配置头文件搜索路径和链接库路径
INCLUDEPATH += $$PWD/qBreakpad/include
CONFIG(debug, debug|release) {
LIBS += -L$$PWD/qBreakpad/lib/debug -lqBreakpad
} else {
LIBS += -L$$PWD/qBreakpad/lib/release -lqBreakpad
}
############ for qBreakpad ############

 

      在main函数添加以下内容,启用崩溃时生成.dmp文件的功能:

六、生成.pdb文件

        将program这个demo程序编译出release版本:

        可见这个demo程序编译出来后体积是比较大的:

        然后将前面下载的cv2pdb工具解压放到目标程序同一个目录:

        在这个目录打开终端,执行命令生成.pdb文件:

cv2pdb.exe   目标程序.exe

        执行成功后,会在目标程序的同级目录下生成.pdb文件,同时也可以看到目标程序的体积变小了:

七、通过.dmp文件追踪程序崩溃的堆栈信息

        运行前面生成的test.exe文件,程序崩溃后会生成.dmp文件:

        使用Visual Studio打开.dmp文件,这里以Visual Studio2022为例:

        点击上图中的“设置符号路径”,将.pdb文件所在路径添加进去:

        击下图中的“使用仅限本机进行调试”:

        如下图所示,可以看到程序崩溃时的堆栈调用情况:

        双击堆栈调用的行内容,将源码文件路径设置一下,便可查看源码及变量的实时值。

八、总结

        在Windows系统下,使用Mingw编译器编译出来的程序,重点和难点是如何生成.pdb文件。而生成.pdb文件的重点有两方面,一是在.pro文件添加-g编译参数,二是使用cv2pdb工具的最新版本,旧版本的cv2pdb工具可能无法生成.pdb文件(这一点困扰了我好久)。

        如果应用程序调用了很多自己开发的动态库,那么动态库的.pro文件也需要添加-g编译参数,并且动态库也需要用cv2pdb工具生成.pdb文件。

        最后,为了方便提取多个文件的.pdb文件,本人写了2个批处理脚本,一个用于提取.exe文件,另一个用于提取.dll文件,我将脚本给出,供大家参考:

        批量提取D:\package\bin目录下所有exe文件的pdb:

@echo off
echo Hello,I am processing pdb files...set OBJECT_HOME=D:\packageset CV2PDB_HOME=%~dp0
CHDIR /D  %OBJECT_HOME%set COMPILE_BIN=%OBJECT_HOME%\binecho "step1: del *.pdb..."
del *.pdbecho "step2: create *.pdb..."set FILE_TYPE_EXE=*.exe
for /r "%COMPILE_BIN%" %%i in (%FILE_TYPE_EXE%)do ( if exist %%i %CV2PDB_HOME%/cv2pdb.exe "%%i" )

        批量提取D:\package\lib目录下所有dll文件的pdb:

@echo off
echo Hello,I am processing pdb files...set OBJECT_HOME=D:\packageset CV2PDB_HOME=%~dp0
CHDIR /D  %OBJECT_HOME%set COMPILE_LIB=%OBJECT_HOME%\libecho "step1: del *.pdb..."
del *.pdbecho "step2: create *.pdb..."set FILE_TYPE_EXE=*.dll
for /r "%COMPILE_LIB%" %%i in (%FILE_TYPE_EXE%)do ( if exist %%i %CV2PDB_HOME%/cv2pdb.exe "%%i" )

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

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

相关文章

.net依赖注入框架 Autofac和MEF的对比

Autofac 默认需要显式注册每个类型,这是它与MEF在模块化设计上的主要区别。以下是具体对比说明:1. Autofac 的基本注册方式 Autofac 必须通过代码明确注册每个需要注入的类型(除非使用特殊扫描机制): var builder new…

Python 使用 asyncio 包处理并 发(使用asyncio包编写服务器)

使用asyncio包编写服务器 演示 TCP 服务器时通常使用回显服务器。我们要构建更好玩一点的示 例服务器,用于查找 Unicode 字符,分别使用简单的 TCP 协议和 HTTP 协议实现。这两个服务器的作用是,让客户端使用 4.8 节讨论过的 unicodedata 模块…

Node.js (Express) + MySQL + Redis构建项目流程

以下是使用 Node.js (Express) MySQL Redis 构建完整项目的详细流程,涵盖环境搭建、架构设计、核心代码实现和部署优化:一、项目初始化 1. 创建项目目录 mkdir my-project cd my-project npm init -y2. 安装基础依赖 npm install express mysql2 redis…

Python3 中使用zipfile进行文件(夹)的压缩、解压缩

一、文件压缩与解压缩模块 zipfile简介 zipfile 是 Python 标准库中用于处理 ZIP 压缩文件的模块,提供了创建、读取、写入、解压 ZIP 文件的完整功能。它支持多种压缩算法,无需安装额外依赖,是处理 ZIP 格式的首选工具。 核心功能与常用类 zi…

在Java客户端使用Redis

目录 第一步:开放Redis外部连接配置 第二步:配置端口转发 第三步:在IDEA中导入依赖 第四步:编写代码命令 连接环境:Java客户端为本地IDEA,Redis服务器安装在云服务器Ubuntu系统中。 第一步:开…

【MySQL】MySQL索引—B树/B+树

目录 1. 数据库索引 1.1 索引的概念 1.2 索引的特点 1.3 索引查询对比普通的查询 1.4 索引的操作 1.5 索引的原理 1.6 B树 1.7 B树 1.8 B树的优点 1. 数据库索引 1.1 索引的概念 数据库的索引是一种特殊的数据结构,里面包含着数据表中所有记录的引用&…

jQuery Mobile 面板详解

jQuery Mobile 面板详解 引言 随着移动设备的普及,移动网页开发变得越来越重要。jQuery Mobile 是一个基于 jQuery 的移动网页开发框架,它提供了一套丰富的 UI 组件和主题,使得开发者可以快速构建出美观、响应式的移动网页。在 jQuery Mobile 中,面板(Panel)是一个非常…

Python中的import和from...import有什么区别?

文章目录 前言 一、import导入模块 导入模块并给它一个别名 语法格式 二、from...import导入特定项 1.导入模块中的特定项 2.导入模块中的所有项 2.1 命名空间核污染 2.2 性能影响 总结 前言 在Python编程中,模块和包的导入机制是编写可维护、可扩展代码的核心。深入理解Pyth…

vscode提示“无法使用 compilerPath 解析配置”解决办法

0 问题描述 使用vscode的Remote-SSH插件连接安装在虚拟机上的Windows10进行远程开发时,出现如下提示:无法使用 compilerPath 解析配置:“D:\mingw64\bin\gcc.exe” 所有包含C库头文件的文件都被标红提示错误:1 问题原因 vscode没有设置正确的…

信噪比(Signal-to-Noise Ratio, SNR)详细介绍

信噪比(Signal-to-Noise Ratio, SNR)信噪比(Signal-to-Noise Ratio,SNR)是衡量信号质量的重要参数,表示有用信号的功率与背景噪声功率的比值。SNR在通信、音频处理、视频处理以及其他电子信号处理领域中具有…

Nginx 相关实验(1)

nginx源码编译 本实验采用nginx源码编译的安装方式,需要准备一个tar包,可从nginx官网上下载。 下载地址:nginx: downloadhttps://nginx.org/en/download.html 将下载好的压缩包传到虚拟机中的自定义目录下 [rootwebserver ~]# ls anacond…

【选型】HK32L088 与 STM32F0/L0 系列 MCU 参数对比与选型建议(ST 原厂 vs 国产芯片)(单片机选型主要考虑的参数与因素)

国产 vs ST 单片机在工业控制中的性能对比分析 HK32L088 与 STM32F0/L0 系列 MCU 参数对比与选型建议 工业控制领域 MCU 选型:国产航顺 HK32 与 ST 原厂芯片深入比较 国产 MCU 是否可替代 ST?基于发电机控制应用的深入评估 从数据手册看 MCU 制造工艺差异:HK32L088 vs S…

LLM Prompt与开源模型资源(1)提示词工程介绍

学习材料:https://www.hiascend.com/developer/courses/detail/1935520434893606913学习时长: 预计 30 分钟学习目的: 了解提示工程的定义与作用 熟悉提示工程的关键技术相关概念 掌握基于昇腾适配的大模型提示工程的入门及进阶指南 提示…

kafka与其他消息队列(如 RabbitMQ, ActiveMQ)相比,有什么优缺点?

Kafka、RabbitMQ 和 ActiveMQ 是三种最主流的消息中间件,它们的设计和适用场景有所不同。 我们可以通过一个简单的表格来快速了解它们的核心区别: 核心对比一览特性 / 维度KafkaRabbitMQActiveMQ核心模型分布式、持久化的日志系统 (Dumb Broker / Smart …

Kubernetes架构和部署

k8s组件 master节点:管理节点 管理平面组件 api server : api gateway controller manager scheduler etcd 数据库 worker节点:被管理节点,运行容器 kubelet:k8s agent container runtime:docker,containerd,cri-o kube-proxy:service 网络 कुबेरनेट…

建造者模式及优化

建造者模式是一种创建型设计模式,它将复杂对象的构建过程与表示分离,使得同样的构建过程可以创建不同的表示。核心思想是指挥者定流程,建造者填细节,通过多个步骤逐步构建对象,并允许灵活组合这些步骤以生成不同配置的…

【09】C++实战篇——C++ 生成静态库.lib 及 C++调用lib,及实际项目中的使用技巧

文章目录1 C 静态库.lib 生成1.1 静态库lib的生成方法和使用方法1.2 创建静态库项目1.3 编写.h 和 .cpp文件1.4 设置 及 生成 DLL2 调用 C 静态库lib2.1 新建LIBtest及测试代码2.2 静态库配置 及代码调用测试3 实际项目中的使用技巧、及通用设置3.1 设置lib输出路径3.2 设置头文…

飞算JavaAI:从写不出代码到丝滑开发,飞算JavaAI把小白从编程深渊捞进了正轨---它都让我怀疑自己是不是多余的!

开篇介绍 对于很多初学者来说,编程是一项既有趣又充满挑战的任务。面对复杂的代码和繁琐的开发流程,常常会感到无从下手。不过,现在有了飞算JavaAI,这一切都将变得简单起来。 它有啥实用功能呢? 比如: …

关于tresos Studio(EB)的MCAL配置之GtmCfg

Generic Time Module通用时钟模块GeneralGtmCfg_DevErrorDetect开发者错误检测开关GtmCfg_DemErrorReporting诊断错误报告开关GtmCfg_VersionInfoApi获取版本信息的接口开关GtmCfg_ConfigSetClockManagementUnitGlobal_Clock_Control_Numerator全局时钟分频器的分子Global_Cloc…

深入探索Weaviate:构建高效AI应用的数据库解决方案

在当今数据驱动的世界中,高效地存储、检索和处理大规模数据成为了AI应用开发的关键挑战。Weaviate作为一个开源的向量搜索引擎,凭借其强大的功能和灵活的架构,正逐渐成为开发者构建智能AI应用的首选工具。本文将深入探讨Weaviate的核心概念、…