使用Windbg分析从系统应用程序日志中找到的系统自动生成的dump文件去排查问题

news/2024/12/22 20:40:15/

目录

1、尝试将Windbg附加到目标进程上进行动态调试,但Windbg并没有捕获到

2、在系统应用程序日志中找到了系统在程序发生异常时自动生成的dump文件

2.1、查看应用程序日志的入口

2.2、在应用程序日志中找到系统自动生成的dump文件

3、使用Windbg静态分析dump文件

3.1、找到函数调用堆栈中相关模块的pdb文件,将pdb文件路径设置到Windbg中

3.2、查看详细的函数调用堆栈,对照着C++源码进行分析

4、总结


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具案例集锦(专栏文章正在更新中...)https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)https://blog.csdn.net/chenlycly/category_11931267.html       近日某个用户反馈,在其Win10的电脑上运行我们的软件,会频繁地出现崩溃闪退的情况,系统弹出程序已经停止运行的提示。我们尝试将Windbg附加到目标进程上分析,但Windbg并没有感知到,后来查看系统中应用程序日志找到系统自动生成的dump文件,然后分析这个dump文件才排查出问题。本文详细讲解这个问题的完整排查过程。

1、尝试将Windbg附加到目标进程上进行动态调试,但Windbg并没有捕获到

       用户反馈,在其Win10的电脑上运行我们的软件,会频繁地出现崩溃闪退问题,系统会弹出程序已经停止运行的提示,如下所示:

程序中安装的异常捕获模块没有感知到崩溃,没有生成包含异常上下文的dump文件。

       既然没有生成dump文件,那我们就尝试将Windbg附加到目标进程上进行动态调试,看看程序发声异常时Windbg能否捕捉到。于是让用户在启动程序时将Windbg附加到程序上,然后按照之前的问题场景去复现问题,一般使用Windbg动态调试时如果程序发声异常,Windbg都会感知到并中断下来,这样就能地问题进行分析了。

       但本问题有点不太一样,复现问题时Windbg并没有第一时间感知到,系统立即弹出了程序已经停止运行的提示。弹出该提示窗口时,Windbg也被冻结住了,没法进行操作了。这种场景还是第一次遇到,很是奇怪!

2、在系统应用程序日志中找到了系统在程序发生异常时自动生成的dump文件

        在日常分析软件异常崩溃问题时,基本都是使用Windbg分析的,要么使用Windbg静态分析dump文件,要么将Windbg附加到进程上进行动态调试。但目前这个问题,静态分析和动态调试都行不通,这就比较棘手了!后来想到,我们可以到系统的应用程序日志中查看一下,看看能不能找到一些线索。

2.1、查看应用程序日志的入口

       我们通过远程软件远程到用户的电脑上,在Win10系统的桌面上,右键点击“此电脑”,在弹出的右键菜单中点击“管理”菜单项,如下所示:

打开计算机管理窗口后,在系统工具节点下,展开事件查看器节点,在该节点下继续展开Windows日志节点,然后点击应用程序节点,这样右边就显示应用程序相关的系统日志了,如下所示:

        一般程序在发生异常时,系统感知到,会自动生成与之相关的日志。于是按照程序出问题时的时间点,在应用程序日志列表中找对应时间点的日志记录。出问题的时间点大概为2023/07/28 14:55,在应用程序日志列表中果然找到了这个时间的日志记录,如上所示。

2.2、在应用程序日志中找到系统自动生成的dump文件

        于是点击上述时间点的记录,在下方的详细信息中看到了问题的相关描述:

错误存储段 ,类型 0
事件名称: BEX
响应: 不可用
Cab Id: 0

问题签名:
P1: XXXXXXX.exe(哈哈,这个地方把程序名称做匿名处理)
P2: 7.0.0.3
P3: 648a1cec
P4: ucrtbase.dll
P5: 10.0.10586.0
P6: 5632d166
P7: 00083472
P8: c0000409
P9: 00000005
P10: 

附加文件:
C:\Users\Kvs\AppData\Local\Temp\WERF6BC.tmp.WERInternalMetadata.xml
C:\Users\Kvs\AppData\Local\Temp\WER53E1.tmp.appcompat.txt
C:\ProgramData\Microsoft\Windows\WER\ReportQueue\AppCrash_XXXXXXX.exe_a57edd93ecda26986177f6523e6d19d6506eb2_d05b1441_cab_15ff59bc\memory.hdmp
C:\ProgramData\Microsoft\Windows\WER\ReportQueue\AppCrash_XXXXXXX.exe_a57edd93ecda26986177f6523e6d19d6506eb2_d05b1441_cab_15ff59bc\triagedump.dmp
WERGenerationLog.txt

可在此处获取这些文件:
C:\ProgramData\Microsoft\Windows\WER\ReportQueue\AppCrash_XXXXXXX.exe_a57edd93ecda26986177f6523e6d19d6506eb2_d05b1441_cab_15ff59bc

分析符号: 
重新检查解决方案: 0
报告 Id: 08632728-2da3-493f-a30c-ffd617076fc3
报告状态: 96
哈希存储段: 

在日志描述信息中,首先看到发生的段错误,然后看到了系统自动生成的dump文件的完整路径:

C:\ProgramData\Microsoft\Windows\WER\ReportQueue\AppCrash_XXXXXXX.exe_a57edd93ecda26986177f6523e6d19d6506eb2_d05b1441_cab_15ff59bc\triagedump.dmp

然后到这个路径中将dump文件拷贝出来。这个应该是系统在检测到程序异常时自动生成的,应该是程序发生异常时包含异常上下文信息的dump文件,使用Windbg静态分析这个dump文件应该就能分析出问题的。

3、使用Windbg静态分析dump文件

        使用Windbg打开dump文件,先输入.ecxr命令切换到发生异常的那个线程中,然后输入kn命令查看该线程的函数调用堆栈,如下所示:

这个函数调用堆栈中看不到具体的函数名和代码的行号,是因为没有加载函数调用堆栈中模块的pdb符号文件的原因。

3.1、找到函数调用堆栈中相关模块的pdb文件,将pdb文件路径设置到Windbg中

        从当前的函数调用堆栈中,可以看到涉及到三个模块:xxlogdll.dll、xxxpsdll.dll和microblogdll.dll,所以我们需要去拿这三个模块的pdb符号文件。使用lm命令查看这三个模块二进制文件的时间戳,通过时间戳到文件服务器上去找pdb符号文件。以microblogdll.dll为例,查看该模块信息的命令为:lm vm microblogdll*,打印出来的模块信息如下:

从图中可以看出,当前的microblogdll.dll文件的时间戳(生成时间)为2023年06月13日09时56分21秒,于是以这个时间点,到文件服务器上找到对应的文件夹,找到对应时间点的pdb符号文件。

        将上述三个模块的pdb符号文件找到,统一拷贝到桌面路径C:\Users\Administrator\Desktop\pdbdir中,然后将pdb文件路径设置到Windbg中,设置的路径如下所示:

C:\Users\Administrator\Desktop\pdbdir;srv*f:\mss0616*http://msdl.microsoft.com/download/symbols
其中,C:\Users\Administrator\Desktop\pdbdir是业务库的pdb符号文件路径;

srv*f:\mss0616*http://msdl.microsoft.com/download/symbols为微软系统库pdb在线下载服务器地址,其中http://msdl.microsoft.com/download/symbols是在线下载服务器地址,f:\mss0616为从在线服务器上下载pdb文件的临时保存地址。

        之所以要设置Windows系统库的pdb在线下载服务器地址,是因为上述函数调用堆栈中包含系统库的模块ucrtbase.dll,我们要查看系统模块中的具体函数调用。有时如果能看到系统模块中的具体函数调用,能更有利于我们分析问题。

3.2、查看详细的函数调用堆栈,对照着C++源码进行分析

        加载pdb文件后,就能看到完整的函数调用堆栈了(能看到具体的函数名及C++代码的行号),如下所示:

从最上面调用的系统库的接口ucrtbase!_invalid_parameter来看,是程序中产生了无效的参数,无效参数引发了程序异常。再沿着函数调用堆栈向上看,是调用C函数vsnprintf函数去格式化数据引发的无效参数,当然肯定不是系统C函数vsnprintf中有问题。还要继续向上看,上面几个是打印日志的接口,然后继续向上,最终找到了调用打印日志接口的上层函数lohttp::CloHttp::OnHttpStackCb,其相关代码片如下:

上述代码中,要将一个char型buffer中的字符串作为日志打印出来,调用的是MiCROBLOG_LOG接口,使用的格式化符%s,要待格式化的参数p,应该也是吻合的,这里似乎并没有问题。如果是有问题,则可能是p指向的内存中的数据有问题,引发底层函数格式化时产生了异常。

       这个代码片段位于组件组维护的模块中,于是将上述函数调用堆栈及相关信息发给组件组的同事,让他们继续排查。其实这个地方有个简单的规避方法,直接在lohttp::CloHttp::OnHttpStackCb函数中将调用MiCROBLOG_LOG接口的那行代码注释掉即可。但这只是规避的办法,还是要搞清楚为什么会引发崩溃的。

4、总结

       这个问题现象比较少见,所以在此详细记录一下。一般情况下,将Windbg附加到进程上进行动态调试时,如果程序发生异常,Windbg应该能感知到并中断下来。结果这个问题中,直接弹出程序停止运行的系统提示框,Windbg并没有感知到。遇到这类情况时,可以尝试到系统的应用程序日志中查看相关记录,可能能找到程序发生异常时系统自动生成的包含异常上下文的dump文件,然后使用Windbg静态分析该dump文件就能分析出问题了。


http://www.ppmy.cn/news/1001888.html

相关文章

网络安全(黑客)自学就业

前段时间,遇到网友提问,说为什么我信息安全专业的找不到工作? 造成这个结果主要是有两大方面的原因。 第一个原因,求职者本身的学习背景问题。那这些问题就包括学历、学校学到的知识是否扎实,是否具备较强的攻防实战…

数据结构 | 搜索和排序——排序

目录 一、冒泡排序 二、选择排序 三、插入排序 四、希尔排序 五、归并排序 六、快速排序 排序是指将集合中的元素按照某种顺序排序的过程。 一、冒泡排序 冒泡排序多次遍历列表。它比较相邻的元素,将不合顺序的交换。每一轮遍历都将下一个最大值放到正确的位…

【css】nth-child选择器实现表格的斑马纹效果

nth-child() 选择器可以实现为所有偶数&#xff08;或奇数&#xff09;的表格行添加css样式&#xff0c;even&#xff1a;偶数&#xff0c;odd&#xff1a;奇数。 代码&#xff1a; <style> table {border-collapse: collapse;width: 100%; }th, td {text-align: cente…

如何将服务开放给用户:构建 API 接口和用户认证的实践指南

如何将服务开放给用户&#xff1a;构建 API 接口和用户认证的实践指南 &#x1f680; 在今天的博客中&#xff0c;我们将探讨一个非常重要且有趣的话题&#xff1a;如何将你的服务开放给用户&#xff1f;无论是构建Web应用、移动应用还是其他服务&#xff0c;开放API接口和用户…

【2023 华数杯全国大学生数学建模竞赛】 C题 母亲身心健康对婴儿成长的影响 Python代码实现

【2023 华数杯全国大学生数学建模竞赛】 C题 母亲身心健康对婴儿成长的影响 1 题目 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c; 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况&#xff0c;如抑郁、焦虑、压力等…

1344:最小花费(最短路)---信息学奥赛一本通

【题目描述】 在n个人中&#xff0c;某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费&#xff0c;请问A最少需要多少钱使得转账后B收到100元。 【输入】 第一行输入两个正整数n,m&#xff0c;分…

许战海咨询方法论系列白皮书在京隆重发布

新时代&#xff0c;面对剧烈变化的竞争环境&#xff0c;企业如何实现结构性增长&#xff1f; 7月31日&#xff0c;许战海咨询最新研究成果——《主品牌进化战略》、《第二招牌增长战略》、《链主品牌&#xff1a;制造业的竞争之王》三本核心方法论白皮书&#xff0c;重磅发布。…

数据结构----c语言复习

数据结构----c语言复习 一.类型 1.类型的种类 char 1个字节 范围-128~127 short 2个字节 范围-32768~32767 int 4个字节 范围-2147483648~2147483647 long 4个字节 范围-2147483648~2147483647 float 4个字节 有效位为6~7位 float 8个字节 有效位为15~16为 unsigned c…