使用Windbg分析从系统应用程序日志中找到的系统自动生成的dump文件去排查问题
目录
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文件就能分析出问题了。
相关文章:

使用Windbg分析从系统应用程序日志中找到的系统自动生成的dump文件去排查问题
目录 1、尝试将Windbg附加到目标进程上进行动态调试,但Windbg并没有捕获到 2、在系统应用程序日志中找到了系统在程序发生异常时自动生成的dump文件 2.1、查看应用程序日志的入口 2.2、在应用程序日志中找到系统自动生成的dump文件 3、使用Windbg静态分析dump文…...

后端技术趋势指南|如何选择自己的技术方向
编程多条路,条条通罗马 后台大佬 后台路线都是面对后台服务器业务,比如web后台服务器,视频后台服务器,搜索后台服务器,游戏后台服务器,直播后台服务器,社交IM后台服务器等等,大部分…...
Delphi XE的原生JSONObject如何判断键值是否存在?
【问题现象】 Delphi XE的原生JSONObject,取出键值的时候如下: //json是传入的参数,里面包括"food_name"等之类的键值,没有food_type键值 procedure XXXXFunciton(json:TJSONObject) var strFoodName,strFoodType:S…...
Go Runtime功能初探
以下内容,是对 运行时 runtime的神奇用法[1] 的学习与记录 目录: 1.获取GOROOT环境变量 2.获取GO的版本号 3.获取本机CPU个数 4.设置最大可同时执行的最大CPU数 5.设置cup profile 记录的速录 6.查看cup profile 下一次堆栈跟踪数据 7.立即执行一次垃圾回收 8.给变量…...

01|Oracle学习(监听程序、管理工具、PL/SQL Developer、本地网络服务介绍)
基础概念 监听程序:运行在Oracle服务器端用于侦听客户端请求的程序。 相当于保安,你来找人,他会拦你,问你找谁。他去帮你叫人过来。 配置监听程序应用场景 Oracle数据库软件安装之后没有监听程序(服务)…...

滴滴数据服务体系建设实践
什么是数据服务化 大数据开发的主要流程分为数据集成、数据开发、数据生产和数据回流四个阶段。数据集成打通了业务系统数据进入大数据环境的通道,通常包含周期性导入离线表、实时采集并清洗导入离线表和实时写入对应数据源三种方式,当前滴滴内部同步中心…...

VBA技术资料MF36:VBA_在Excel中排序
【分享成果,随喜正能量】一个人的气质,并不在容颜和身材,而是所经历过的往事,是内在留下的印迹,令人深沉而安谧。所以,优雅是一种阅历的凝聚;淡然是一段人生的沉淀。时间会让一颗灵魂࿰…...
Shell脚本学习3
文章目录 Shell脚本学习3函数函数定义及使用函数参数获取函数返回值 重定向输入输出重定向 其他Here Document/dev/null 文件Shell文件包含获取当前正在执行脚本的绝对路径按特定字符串截取字符串 Shell脚本学习3 函数 函数定义及使用 函数可以让我们将一个复杂功能划分成若…...

代理模式--静态代理和动态代理
1.代理模式 定义:代理模式就是代替对象具备真实对象的功能,并代替真实对象完成相应的操作并且在不改变真实对象源代码的情况下扩展其功能,在某些情况下,⼀个对象不适合或者不能直接引⽤另⼀个对象,⽽代理对象可以在客户…...

C++容器——list的模拟实现
目录 一.list的基本结构 二. 接下来就是对list类构造函数的设计了: 三.链表数据的增加: 四.接下来就是迭代器的创建了: 四.简单函数的实现: 五.构造与析构 六.拷贝构造和赋值重载 传统写法: 现代写法: 七.迭…...
VUE3 祖孙组件传值调用方法
1.在 Vue 3 中,你可以使用 provide/inject 来实现祖孙组件之间的传值和调用方法。 首先,在祖组件中使用 provide 来提供数据或方法,例如: // 祖组件 import { provide } from vue;export default {setup() {const data Hello;c…...
我的网安之路
机缘 我目前从事网安工作,一转眼我从发布的第一篇文章到现在已经过去了4年了,感慨时间过得很快 曾经我是一名Java开发工程师所以我的第一篇文章是跟开发相关的那个时候还是实习生被安排 一个很难的工作是完成地图实时定位以及根据GPS信息模拟海上追捕,这对刚入职的我来说很难 …...
langchain-ChatGLM源码阅读:webui.py
样式定制 使用gradio设置页面的视觉组件和交互逻辑 import gradio as gr import shutilfrom chains.local_doc_qa import LocalDocQA from configs.model_config import * import nltk import models.shared as shared from models.loader.args import parser from models.load…...

<C++>二、 类和对象
1.面向对象和面向过程 C语言是面向过程的,关注的是过程,分析出求解问题的步骤, 通过函数调用逐步解决问题。 C是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。 2. C类 C…...

【HttpRunnerManager】搭建接口自动化测试平台实战
目录 一、需要准备的知识点 二、我搭建的环境 三、搭建过程 四、访问链接 五、两个问题点 【整整200集】超超超详细的Python接口自动化测试进阶教程,真实模拟企业项目实战!! 一、需要准备的知识点 1. linux: 安装 python3、nginx 安装和…...
【adb】adb常用命令
Android Debug Bridge (adb) Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令可用于执行各种设备操作,例如安装和调试应用。adb 提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。它…...

SAP 委外副产品业务
SAP 委外副产品业务 1.订单bom设置数量为负 2.采购收货时,副产品O库存增加,545 O 借:原材料 贷:委外加工-发出材料 3.从O库存调拨回本地库存,542...

高并发编程-2. 并发级别
此文章为笔记,为阅读其他文章的感受、补充、记录、练习、汇总,非原创,感谢每个知识分享者。 原文 文章目录 阻塞无饥饿(Starvation-Free)无障碍(Obstruction-Free)无锁(Lock-Free)无等待 由于临界区的存在,多线程之间的并发必须受…...

牛客网Verilog刷题——VL47
牛客网Verilog刷题——VL47 题目答案 题目 实现4bit位宽的格雷码计数器。 电路的接口如下图所示: 输入输出描述: 信号类型输入/输出位宽描述clkwireIntput1时钟信号rst_nwireIntput1异步复位信号,低电平有效gray_outregOutput4输出格雷码计数…...

Redis以及Java使用Redis
一、Redis的安装 Redis是一个基于内存的 key-value 结构数据库。 基于内存存储,读写性能高 适合存储热点数据(热点商品、资讯、新闻) 企业应用广泛 官网:https://redis.io 中文网:https://www.redis.net.cn/ Redis…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...

Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...

简约商务通用宣传年终总结12套PPT模版分享
IOS风格企业宣传PPT模版,年终工作总结PPT模版,简约精致扁平化商务通用动画PPT模版,素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...