基于开源CrashRpt与微软开源Detours技术深度改造的异常捕获库分享

目录

1、异常捕获模块概述

2、为什么需要异常捕获模块?

3、在有些异常的场景下是没有生成dump文件的

4、开源异常捕获库CrashRpt介绍

5、对开源库CrashRpt的改进


C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html       最近有很多朋友问到异常捕获机制及开源异常捕获库的问题,今天有时间,就给大家说说异常捕获库相关的内容

1、异常捕获模块概述

       异常捕获模块是内置在程序中的,当程序发生异常,异常捕获模块感知(捕获)到,自动生成包含异常上下文的dump,文件,可能同时也会生成程序版本等信息的日志文件。事后,我们可以取来这些日志及dump文件去分析软件发生异常崩溃的原因。

       异常捕获模块一般是以函数回调的方式通知给主程序,此时主程序可以弹出相关的提示框,提示用户程序发生了异常崩溃,用户可以重新运行程序。程序中内置异常捕获模块,已经成为一种标配,大部分程序都会自带异常捕获模块。以PC版的微信为例,当微信发生崩溃时,其内置的异常捕获模块会捕获到异常并生成日志及dump文件,同时会弹出如下的发送错误报告的提示框:

提示框的下方会自动带上崩溃相关的文件,其中最后一个文件就是包含异常上下文信息的dump文件,点击确定则会将这些文件发送到腾讯远端的后台服务器上。腾讯后台的运维人员会收到通知,然后到服务器上将dump等文件下载下去分析。

       有些软件可能没有上传崩溃日志到服务器的功能,捕捉到异常时会自动将dump文件保存到指定的路径中,事后可以到该路径中取到对应的dump文件。如果客户机器上遇到崩溃,可以和客户联系,让客户帮忙从对应的路径中取来出dump文件发过去。

2、为什么需要异常捕获模块?

       在日常项目开发维护的过程中,会遇到这样那样的异常崩溃,分析这些异常崩溃最常用、最重要的途径就是事后分析异常发生时生成的dump文件。

       要分析软件异常崩溃,首先要有dump文件,那包含异常上下文信息的dump文件是如何生成的呢?以前我们讲过生成dump文件的三种方式:

1)通过内置的异常捕获模块,去捕获软件发生的异常崩溃,自动生成包含异常上下文的dump文件。这是生成dump文件最常用的方式。
2)可以在动态调试的Windbg中,使用.dump命令手动导出包含异常上下文信息的dump文件。为啥要导出dump文件呢?既然Windbg在动态调试,为啥不能直接分析呢?在条件允许的情况下可以直接在Windbg中分析,但一时半会分析不出来问题时或者不能长时间占用用户的电脑时,就需要导出dump文件,供事后分析了。
3)可以从Windows任务管理中导出dump文件。在任务管理器的进程列表中找到目标进程,右键点击,在弹出的右键菜单中点击导出转储文件即可。这种方式首先要求出问题的程序进程还存活着的(进程还在的),比如程序发生卡死、死循环或者程序弹出报错提示框时(弹出报错提示框时,如果不点击提示框中的按钮将提示框关闭掉,则程序进程还在的)。

其中,通过异常捕获模块去生成dump文件,是最常用的一种方式。事后分析dump文件,也是我们分析和排查软件异常崩溃问题最常用的方法。

       关于dump文件及生成方式的详细说明,可以查看我之前写的文章:

dump文件类型与dump文件生成方法详解icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/127991002       有人可能会说,遇到问题,我直接使用IDE去调试不就行了,我不需要什么dump文件的!如果这样说,只能说其处理异常问题的经验太有限了!因为有些问题可能是很难复现的,或者问题只在客户的环境中复现,这样也就无从去调试代码了。再就是程序中有多个模块,不同的模块由不同的开发组负责,如果程序崩溃在底层的模块中,还需要底层去调试代码。底层模块的开发人员需要搭建调试环境,然后使用附加到进程的方式去调试代码。

       如果在程序中安装了异常捕获模块,在程序发生异常时自动生成包含异常上下文的dump文件,我们直接将dump文件取来分析就好了,就不用老想着如何去复现问题了。直接使用Windbg静态分析dump文件,查看发生异常的那条汇编指令以及发生异常的函数调用堆栈,一般就能快速地定位问题了,可以有效地提高我们排查问题和解决问题的效率。

当然,并不是说有了dump文件,就一定不需要复现问题了。在个别情况下,通过分析dump文件很难排查出问题时,可以尝试去复现问题(找到复现问题的操作规律),找到问题发生的场景,这样可能去辅助分析问题的。所以有时候,为了排查分析问题,我们需要使用多种手段与方法的!


         在这里,给大家重点推荐一下我的几个热门畅销专栏:

专栏1:(该专栏订阅量已达到420多个,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!)

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据近几年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的实战问题分析实例,带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

专栏中的文章均是通过项目实战总结出来的(通过项目实战积累了大量的异常排查素材和案例),有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2: 

C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战为基础,总结并讲解一些的C/C++基础与进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域的多个方面的内容,同时给出C/C++及网络方面的常见笔试面试题,并详细讲述Visual Studio常用调试手段与技巧!

专栏3: 

开源组件及数据库技术icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html

以多年的开发实战为基础,分享一些开源组件及数据库技术!


3、在有些异常的场景下是没有生成dump文件的

       即便程序中安装了异常捕获模块,在某些异常的场景下,可能也是没有生成dump文件的。这里面是有多种原因的。

       首先,异常捕获模块不是万能的,只能捕捉(感知)到大部分的异常,但不能捕获所有的异常,这和异常捕获模块的捕获机制的缺陷有关。其次,可能在生成dump文件时产生了二次崩溃,生成的dump文件是空的。对于没有生成dump文件的场景,就只能尝试Windbg的动态调试了,将Windbg附加到目标进程上,和目标进程一起跑,一旦程序发生异常,作为正在调试的调试器Windbg,会第一时间感知到并中断下来,此时去查看函数调用堆栈去分析就好了。

       再者就是,程序只是发生了闪退,但程序没有发生异常崩溃。比如我们在项目中遇到的两个典型的场景,一个是在用开源库jsoncpp时错误地解析json串中的字段类型时,jsoncpp发现类型错误,就直接认为是致命的,直接调用abort接口将进程终止了。还有一个场景是,我们在使用开源库WebRTC时,当调用malloc动态申请内存失败时(可能是程序内存不足导致的申请失败),malloc返回NULL,WebRTC认为内存申请不到了,业务没法正常运行下去,认为这是致命的,程序没有继续活着的意义了,直接调用abort强行将进程终止了。

       对于这两种强行终止进程的场景,并没有发生C++上的异常,只是代码人为地终止了进程。从现象上看,程序直接闪退了(没了),给人一种程序发生异常崩溃导致程序闪退的感觉,其实程序并没有发生异常崩溃,是代码人为终止进程的。对于这种强行终止进程的场景,就需要使用Windbg动态调试了,将Windbg附加到目标进程上,和目标进程一起跑,C函数abort内部会产生一个特殊的异常,让让调试器Windbg中断下来,此时查看函数调用堆栈,就知道是调用了abort强行终止进程的,然后继续结合函数调用堆栈去分析问题了。

       对于使用开源jsoncpp和开源WebRTC遇到的强行终止进程的问题,具体细节可以去查看我之前写的文章:

C++程序中执行abort等操作导致没有生成dump文件的问题案例分析icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/129003869       此外,有时即使拿到了dump文件,可能也需要用Windbg进行动态调试的。比如从现有dump文件中分析不出问题时或者看到的函数调用堆栈不全或有问题,可以尝试使用Windbg进行动态调试。再比如,以前我们讲过,有时可能要查看相关变量的值,这些变量的值可能是排查问题的关键线索,但异常捕获模块生成的dump文件是小dump文件(比如几百KB或几MB,只保存了小部分内存信息),只能部分变量的值,有些变量的值是看不到的,但这些变量可能是分析问题的关键线索,这时也可以尝试使用Windbg进行动态调试,动态调试时可以看到所有变量的值。

       对于通过查看相关变量值去快速定位问题的案例,可以查看我的文章:
通过查看Windbg中变量值去定位C++软件异常问题icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125731044       对于很好复现的问题,使用Windbg动态调试很方便的,将Windbg挂到目标进程上,快速复现问题,Windbg感知到异常中断下来,就可以立即分析了。对于不好复现或者很难复现的问题,只能每次启动程序测试时都将Windbg挂上去,等待复现为止。

      关于何时使用Windbg静态分析与动态调试,可以查看我的文章:

何时使用Windbg静态分析?何时使用Windbg动态调试?icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131806819

4、开源异常捕获库CrashRpt介绍

       如何去设计异常捕获库呢?大家都会想到使用系统API函数SetUnhandledExceptionFilter去设置异常回调,当程序发生异常时就会调用设置的回调函数,然后在回调函数中调用API函数MiniDumpWriteDump去生成dump文件。但使用这种方式,缺陷很明显,很多异常捕获不到,可以选择开源的异常捕获库。

       常见的开源捕获库有CrashRpt和Google开源的CrashPad,今天我们来重点介绍一下CrashRpt。CrashRpt 是一个免费的、轻量级的开源错误报告库开源库,旨在拦截C++程序中的异常,收集有关崩溃的技术信息并通过互联网向软件供应商发送错误报告,用于 Windows C++应用程序中。

1)CrashRpt 可以处理主线程和用户模式程序的所有工作线程中的异常:SEH 异常(Structured Exception Handling 结构化异常处理)、未处理C++类型异常、信号和 CRT (C运行时)错误。在 CrashRpt 可以处理的错误类型中,有:NULL 指针分配、访问冲突、无限递归、堆栈溢出、内存耗尽等。
2)CrashRpt能生成错误报告,包括小型崩溃转储minidump文件、可扩展的崩溃描述XML文件、应用程序自定义的文件(如程序日志文件)等。

5、对开源库CrashRpt的改进

       CrashRpt对多线程支持的不好,导致很多异常捕获不到。另外,CrashRpt在捕获到异常时,会自动自动截屏、录制视频和发送邮件,这些功能其实是什么用处的,直接把它们裁剪掉。对于发送邮件,CrashRpt中是直接使用socket实现的,其稳定性不太好,如果需要用到这个功能,可以使用开源库libcurl,libcurl中支持POP3和SMTP邮件协议。

       为了解决CrashRpt很多异常捕获不到的问题,我们首先添加了对多线程的支持,然后引入了微软的Detours技术,有效地提高了异常捕获的效率,基本可以捕获90%以上的异常。捕获到异常后,就会生成dump文件,事后使用Windbg去分析dump文件即可。对于没捕捉到的异常的场景,则需要使用使用Windbg进行动态调试了,上面这些场景我也详细讲到了。

如果要获取到该改进的异常捕获库,可以联系微信kvsthingking

       关于如何使用Windbg去静态分析dump文件,可以查看我的文章:
使用Windbg分析dump文件的一般步骤及要点详解icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/130873143      关于如何使用Windbg去动态调试目标进程,可以查看我的文章:

使用Windbg调试目标进程的一般步骤及要点详解icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/135484906

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

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

相关文章

【图说】VMware Ubuntu22.04 详细安装教程

前言 无论是从事 Linux 开发工作,还是希望电脑运行双系统,VMware 虚拟机都是我们日常工作不可或缺的工具。本章将会重点介绍 VMware 安装流程,以及在 VMware 上如何运行、使用 Ubuntu22.04 系统。 一、VMware 下载安装 1.1 VMware 官网下载…

TensorFlow文件读取 --TFRecords文件

TFRecords文件 是一种二进制文件,能够很好的利用内存,更方便复制和移动,并且不需要单独的标签文件 使用步骤 1)获取数据 2)将数据填入到Example协议内存块(protocol buffer) 3)将协…

001-谷粒商城-微服务剖析

1、架构图 还是很强的,该有的都有 2、微服务模块 SpringCloudAlibaba组件包括 SentinelNacosRocketMQSeata 搭配SpringCloudAlibaba组件 OpenFeignGateWayRibbn gateway使用了SpringWebFlux,前几天研究到,为什么springboot不直接使用Spri…

阿里云mysql8.0 this is incompatible withsql mode=only full group by

阿里云RDS中mysql5.6升级为8.0后,出现如下问题: ### Error querying database. Cause:java.sql.SQLSyntaxErrorException: Expression #1 of SELECT listis not in GROUP BY clause and contains nonaggregatedcolumn temp.product_id which is not fun…

2024抖店新政策!抖音小店的发展趋势!新手必看!

哈喽~我是电商月月 准备开抖店的新手朋友注意了,最近抖音严查无货源违规商家,还发布了取消新手期的政策,这说明了两点 1. 生态环境正在改变 无规矩不成方圆,违规的都是故意放错类目以及,靠S单非法获得销量&#xff…

流量计如何进行校准?

什么是流量计?流量计是指示被测流量和(或)在选定的时间间隔内流体总量的仪表。简直研制,流量计是用于测量管道或明渠中流体流量的一种仪表。流量计种类繁多,又分为有差压式流量计、转子流量计、节流式流量计、细缝流量…

Linux信号(保存)

个人主页:Lei宝啊 愿所有美好如期而遇 前言 Linux信号(产生)-CSDN博客,上一个章节我们详细介绍了信号是什么,为什么要有信号,怎样产生信号,以及信号产生的几个问题,这个章节我们将介绍信号的保存。 我们…

嵌入式linux学习之arm开发板移植ssh

1.下载源码 (1)zlib 下载网址:http://www.zlib.net/fossils/ 教程中版本选择的是: zlib-1.2.11.tar.gz (2)openssl下载网址:https://www.openssl.org/source/mirror.html 教程中版本选择的是: openssl-1.1…

设计模式-迭代器模式(Iterator)

1. 概念 迭代器模式是一种行为型设计模式,它提供了一种统一的方式来访问集合对象中的元素。迭代器模式的核心思想是将遍历集合的责任封装到一个单独的对象中,这样可以避免暴露集合内部的表示方式。这种模式通常用于提供一种方法来访问一个容器对象中各个…

使用 Docker 部署 Draw.io 在线流程图系统

1)介绍 Draw.io GitHub:https://github.com/jgraph/drawio Draw.io 是一款开源的绘制流程图的工具,拥有大量免费素材和模板。程序本身支持中文在内的多国语言,创建的文档可以导出到多种网盘或本地。无论是创建流程图、组织结构图…

如何帮助中小企业建立数字化的能力?

中小企业建立数字化的能力,可以从以下几个方面着手: 1、开展数字化评估:中小企业首先需要对自己的数字化基础水平和企业经营管理现状进行评估,这包括了解企业在数字化方面的现有能力和需求,以及内外部转型资源的可用性…

[创业之路-106] :经济学十大陷阱与核心思想:系统论、社会进化论、周期论、阴阳互转论

目录 前言: 一、流动性陷阱。 二、中等收入陷阱。 三、修昔底德陷阱。 四、塔西佗陷阱。 五、金德尔伯格陷阱。 六、卢梭陷阱。 七、拉美陷阱。 八、阿喀琉斯之踵。 九、布拉德伯里悖论。 十、李约瑟之谜 结论:上述陷阱的…

AI智能客服机器人原来这么好用,企业再不使用就落伍了!

随着人工智能技术的不断成熟,AI智能客服机器人已经变得越来越智能,它们正逐渐成为企业提供客户服务的强大助手。企业若不开始部署这种高效的技术,可能会在竞争中失去先机。下面,让我们来看看AI智能客服机器人为何如此好用&#xf…

vue +antvX6 根据节点与线,动态设置节点坐标生成流程图

需求 vue2 + antvX6完成流程图,但只有节点与线,没有节点的坐标,需要根据节点的顺序显示流程图。 需求: 1.根据数据动态生成对应的节点与线; 2.节点不能重叠; 3.节点与线可拖拽; 4.因为线存在重叠可能,所有鼠标移入时线必须高亮显示(红色),鼠标移出复原; 5.要求有…

Spring-基于xml自动装配

版本 Spring Framework 6.0.9​ 1. 定义 Spring IoC容器在无需显式定义每个依赖关系的情况下,根据指定的策略,自动为指定的bean中所依赖的类类型或接口类型属性赋值。 2. 关键配置元素 BeanDefinitionParserDelegate类定义了autowire属性的属性值&…

绿联 安装transmission

绿联 安装transmission及中文UI 1、镜像 linuxserver/transmission:latest 2、安装 2.1、创建容器 按需配置权重。 2.2、基础设置 2.3、网络 桥接即可。 注:如果使用IPV6,请选择"host"模式。 注:如果使用IPV6,请选…

Git禁止松散对象loose objects弹窗

打开仓库时,弹窗如图 This repository currently has approximately XXXX loose objects.解决办法:见How to skip “Loose Object” popup when running ‘git gui’ Git v1.7.9 或以上版本,执行git config --global gui.gcwarning false

【计算机毕业设计】面向学生成绩分析系统产品功能介绍——后附源码

🎉**欢迎来到琛哥的技术世界!**🎉 📘 博主小档案: 琛哥,一名来自世界500强的资深程序猿,毕业于国内知名985高校。 🔧 技术专长: 琛哥在深度学习任务中展现出卓越的能力&a…

NIO之ByteBuffer

NIO中的ByteBuffer是缓冲区,其中有几个比较重要的属性capacity,position和limit。 capacity: 其中,capacity是缓冲区的容量大小,在分配内存空间后不会改变。 limit: limit是限制位置,在读写模…

前端crypto-js, 文件加密,判断相同文件、图片(MD5,SHA256)

文章目录 前情提要应用场景实战解析最后前情提要 大家好,今天我们来接触一个库crypto-js 没错,上面是有道翻译的截图,为了我们得到的信息更权威,这个库是用来加密的,但介绍是说,已经停止维护,但并不影响我们在前端项目中的使用,所以学学也没有坏处 应用场景 判断图片…