软件崩溃时VS中看不到有效的调用堆栈,使用Windbg动态调试去分析定位

news2025/2/24 14:58:29

目录

1、问题说明

2、使用Windbg查看崩溃时详细的函数调用堆栈

3、将Windbg中显示的函数调用堆栈对照着C++源码进一步分析

4、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html       最近在使用VS调试代码的过程中发生了异常崩溃,在VS中看不到详细的函数调用堆栈,使用Windbg去动态调试目标进程则可以看到详细的函数调用堆栈,进而可以去详细分析崩溃问题。这个问题有一定的代表性,本文详细讲述一下这个崩溃问题的分析过程。

1、问题说明

       在调试软件的新功能时,刚加入一个正在发送桌面共享的会议,软件就发生了崩溃: 

且问题是必现的。此时,切换到函数调用堆栈窗口中查看函数调用堆栈,如下所示:

从堆栈中只能看到崩溃在mediasdk.dll模块中,但看不到详细的函数调用堆栈。这种情形下,使用VS排查很不方便,还是使用Windbg排查崩溃问题要顺手很多。


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

专栏1:(该专栏订阅量接近350个,有很强的实战参考价值,广受好评!)

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

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


2、使用Windbg查看崩溃时详细的函数调用堆栈

       从崩溃时报错的提示框来看:

程序中访问了一个很小的内存地址0x00000003,产生了内存访问违例,第一感觉是不是访问了空指针导致的,但这也只是最开始时的感觉,还要结合后续分析才能找出最终问题的。

       当前这个问题是在Debug下调试出现的,且是必现的,所以先直接启动Debug版本的程序,然后将Windbg附加到程序进程上,然后加入一个正在发送桌面共享的会议中,然后复现崩溃,Windbg中断下来,如下所示:

然后输入kn命令查看此时的函数调用堆栈:

因为没有加载相关模块的pdb文件,所以堆栈中看不到具体的函数名及代码的行号。然后根据堆栈中涉及到的模块,使用lm命令查看模块的时间戳,然后通过时间戳到文件服务器上找到模块对应的pdb文件。这个地方有两个细节需要注意一下:

1)不需要找出堆栈中所有模块的pdb文件,离崩溃点最近的1-2个模块即可,当需要更上层模块的详细函数信息时,再去获取对应模块的pdb文件。
2)加载pdb文件时,会严格校验二进制文件与pdb文件的时间戳,要完全一致才能加载成功,否则会加载失败。比如昨天编译的库和今天编译的库,即使代码没修改,二进制文件和pdb文件都不能交叉配对使用,因为严格校验时间戳。

       拿来pdb文件后,将pdb文件的路径设置到Windbg中,然后重新输入kn命令查看加载pdb符号后的函数调用堆栈:

从函数调用堆栈中可以看到,业务库中调用C函数vsnprintf_s去格式化字符串,最终引发了异常。但调用堆栈最上面的几行是运行时库ucrtbased.dll中,显示的偏移地址较大,看不到系统库中具体的函数名,但有时可能需要查看系统库中具体接口,对分析问题可能很关键!那如何找到系统库的pdb符号文件呢?其实很简单!对于Windows系统库,只需要设置微软在线pdb下载地址就可以了,如下所示:

srv*f:\mss0616*http://msdl.microsoft.com/download/symbols

其中,http://msdl.microsoft.com/download/symbols是微软在线pdb下载地址,f:\mss0616是下载pdb文件时在本机上的缓存路径。按照这个格式来写就可以了。当然程序业务库的pdb路径也要存在,增加新的pdb路径时,直接在现有的路径下加上英文分号,然后将新的路径追加到末尾即可,比如:

C:\Users\admin \Desktop\pdbdir;srv*f:\mss0616*http://msdl.microsoft.com/download/symbols

设置微软在线pdb下载地址后,就可以看到系统库的接口了,如下所示:

其实在本例中,不需要查看系统库中的具体接口就能定位问题了,此处我之所以加到加载系统库pdb文件,是为了说明有时可能会比较关键!

       关于如何查看二进制文件的时间戳以及如何将pdb文件所在的路径设置到Windbg中,已经多次讲过,此处就不详细展开了,如果需要查看,可以参看我之前写的文章:
使用Windbg静态分析dump文件的一般步骤及要点详解icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/130873143

3、将Windbg中显示的函数调用堆栈对照着C++源码进一步分析

       当我看到函数堆栈中因为调用vsnprintf_s接口去格式化字符串产生了崩溃,我第一反应可能是待格式化的参数与使用的格式化符不一致导致的,这是格式化字符串产生崩溃的一种最常见的原因。比如整型变量错误地是用字符串格式化符%s。还有一种隐蔽性较强的场景,带格式化的参数类型长度与格式化符的长度不一致,比如64位整型参数(占用8字节)使用对应四字节的%d去格式化,这种场景有较强的隐蔽性,不熟悉的可能很难看出问题,即使能看出来,可能也搞不清楚引发异常的根本原因。对于这种隐蔽的场景,我前段时间在项目中遇到过,也发表了对应的博客文章:(深度分析了因为格式化符与带格式化参数的类型不匹配引发崩溃的根本原因)
UINT64整型数据在格式化时使用了不匹配的格式化符%d导致其他参数无法打印的问题排查icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/132549186感兴趣的可以去看看。

       于是根据函数调用堆栈中显示的cpp名称和代码的行号,到C++源码中找到调用vsnprintf_s格式化接口的函数,此处为啥会有多行记录呢?因为我们对相关接口做了多层封装。我们只要找添加打印的那个函数即可,如下所示:

因为我最开始就怀疑可能是带格式化的参数类型与格式化符不一致导致的,所以一看到源码,我一眼看出了问题,一个枚举类型的整型值居然使用了字符串格式化符%s,这就是问题所在了。

       经查看,这个枚举值就是3,格式化函数内部在解析格式化串时,当看到%s格式化符时,会把传入的对应参数值3,当成一个字符串的首地址,即会到0x00000003地址的内存中去读取字符串,而这个0x00000003地址,是很小的内存地址,小于64KB地址值的内存区域是禁止访问的,所以产生了内存访问违例,产生了崩溃。这个问题修改起来很简单,将%s换成%d就好了。

      关于格式化函数内部时如何解析格式化符,以及如何根据格式化符找到对应的带格式化参数的可以参见我的这篇文章:

UINT64整型数据在格式化时使用了不匹配的格式化符%d导致其他参数无法打印的问题排查icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/132549186       至于为什么会产生这个问题,应该是开发人员手误导致的,也有可能打印日志的这行代码是从其他地方直接拷贝过来的,没有检查格式化符是否合适,就直接提交代码了。写代码时还是要严谨一点比较好!

4、最后

       大家在日常工作中要去主动排查问题,排查的问题多了,见过的问题场景就多了,经验就更丰富了,在后面遇到问题时思路就会更多,排查的更迅速了!特别是一些“难缠”问题,更锻炼人,能学到的更多!在问题中学习,在问题中成长,在问题中积累经验!

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

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

相关文章

JavaWeb(七)

一、Mybatis概念 MyBatis 是一款优秀的持久层框架,用于简化JDBC开发,解决了原生JDBC硬编码和手动封装结果集的问题。 JavaEE的三层架构分为Controller(表现层)、Service(业务层)、Mapper(持久层)。 持久层负责将数据保存到数据库的那一层代码。使用了…

【开源】基于Vue+SpringBoot的数据可视化的智慧河南大屏

项目编号: S 059 ,文末获取源码。 \color{red}{项目编号:S059,文末获取源码。} 项目编号:S059,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 数据模块 …

让我们向您介绍葡萄酒中的皮诺家族

对于那些喜欢浏览商店里的葡萄酒通道或餐厅的葡萄酒菜单的人来说,你可能也注意到了类似名称的葡萄酒,即灰皮诺和黑皮诺葡萄酒。这葡萄酒有什么区别?他们有任何相似之处吗?今天,我们将一探究竟!让我们了解一…

Web端功能测试的测试方向有哪些?

一、功能测试 1.1链接测试 链接是web应用系统的一个很重要的特征,主要是用于页面之间切换跳转,指导用户去一些不知道地址的页面的主要手段,链接测试一般关注三点: 1)链接是否按照既定指示那样,确实链接到…

uniapp基于u-grid-item九宫格实现uCharts秋云图表展示

uniapp基于uView的UI组件u-grid-item九宫格实现uCharts秋云可视化图表展示 这里使用uView的u-grid-item九宫格组件去显示图标排列 九宫格可以做成多列&#xff0c;移动设备上可以通过左右滑动进行展示 <template><div><div style"text-align: center;font…

msvcp110.dll文件丢失修复教程

本文将详细介绍找不到msvcp110.dll的五个解决方法&#xff0c;并解释msvcp110.dll丢失的原因和其对电脑的作用。 首先&#xff0c;让我们来了解一下msvcp110.dll丢失的原因。msvcp110.dll是Microsoft Visual C 2012 Redistributable Package的一部分&#xff0c;它是用于支持C…

1.qml-3D入门讲解介绍

本章我们来学习QML 3D教程&#xff0c;QML 3D能够支持windows linux等多平台跨平台并且显示效果大部分一致&#xff0c;非常方便&#xff0c;学习的qt版本最低为qt6.5。 要使用qml 3D类&#xff0c;需要导入QtQuick3D模块。 这是使用空间渲染器和场景图的 QML 前端。目前&…

在Linux上优化HTTP服务器的性能

在Linux上优化HTTP服务器的性能是一个涉及多个方面的任务&#xff0c;包括服务器硬件、网络设置、软件配置和内容优化。以下是一些关键的优化建议&#xff1a; 选择合适的HTTP服务器软件 Linux上有多种HTTP服务器软件&#xff0c;如Apache、Nginx、Lighttpd等。选择适合您需求…

做外贸会遇到的一些误区

很多时候&#xff0c;我们喜欢用大多数的情况去给客户提前下某种定义&#xff0c;当我们内心已经种下某种想法的时候&#xff0c;我们在对待事情的时候就会明显的不同。 但是事实上&#xff0c;其实每一个客户都是一个独特的存在&#xff0c;都是一个新的客户&#xff0c; 新的…

npm私有源构建项目下载依赖报错

Jenkins构建项目报错&#xff0c;依赖找不到 Error: Couldnt find any versions for "babel/helper-module-imports" that matches "^7.22.15"at MessageError.ExtendableBuiltin (/data1/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/…

关于清理系统错误内存转储文件的相关知识,看这篇文章就够了

当你的电脑崩溃,遇到类似蓝屏死机(BSOD)的情况时,Windows操作系统会将内存转储到硬盘上的某个位置。你可以删除这些系统错误内存转储文件以释放磁盘空间。 如何使用磁盘清理删除系统错误内存转储文件 如果内存转储文件随着时间的推移而增长,请删除该文件以恢复硬盘空间。…

文件下载保存接口的创建_FastAPI

文件下载保存接口的创建 功能描述实现代码功能演示 功能描述 在网页上对数据进行下载保存处理。例如点击网页上的保存按钮&#xff0c;会把文件下载到本地。下面就是对下载保存功能的实现。 实现代码 gpt_router.get("/export_data") async def export_data():# 需…

感觉到自己思想扭曲了

突然觉得自己思想有点扭曲。 ​起因是近期备婚&#xff0c;需要给男方家人买衣服。问男朋友妹妹衣服预算多少&#xff0c;说是500内&#xff0c;然后想想自己这个新娘子&#xff0c;那一身衣服绞尽脑汁凑满减不到300。再联想到装饰新房&#xff0c;新房买家具&#xff0c;为了省…

【性能测试】LR录制回放事务检查点

前言 上一次推文我们分享了性能测试分类和应用领域&#xff0c;今天带大家学习性能测试工作原理、事务、检查点&#xff01;后续文章都会系统分享干货&#xff0c;带大家从0到1学会性能测试&#xff0c;另外还有教程等同步资料&#xff0c;文末免费获取~ 01、LR工作原理 ​通…

CentOS或RHEL安装code-server(vscode-web)

下载rpm安装包 网络下载或者下载到本地再上传到服务器&#xff0c;点击访问国内下载地址&#xff0c;不需要积分curl -fOL https://github.com/coder/code-server/releases/download/v4.19.1/code-server-4.19.1-amd64.rpm安装 rpm -i code-server-4.19.1-amd64.rpm关闭和禁用…

配电房一体化环境监控系统

配电房一体化环境监控系统是一种综合运用多种传感器、物联网、云计算、大数据等技术的智能化监控系统&#xff0c;依托电易云-智慧电力物联网&#xff0c;实现对配电房内环境、设备运行状态等信息的实时监测和预警&#xff0c;提高配电房的安全性和可靠性。以下是配电房一体化环…

C //例10.1 从键盘输入一些字符,逐个把它们送到磁盘上去,直到用户输入一个“#”为止。

C程序设计 &#xff08;第四版&#xff09; 谭浩强 例10.1 例10.1 从键盘输入一些字符&#xff0c;逐个把它们送到磁盘上去&#xff0c;直到用户输入一个“#”为止。 IDE工具&#xff1a;VS2010 Note: 使用不同的IDE工具可能有部分差异。 代码块 方法&#xff1a;使用指针&…

CUDA简介, 配置和运行第一个CUDA程序(Windows和Linux)

CUDA简介 CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由NVIDIA开发的一种通用并行计算架构。CUDA允许程序员利用NVIDIA GPU的并行计算能力&#xff0c;加速各种计算密集型应用程序。 CUDA技术基于GPU的并行计算原理。传统的CPU处理器拥有少量的核心&…

Zabbix自定义监控内容

自定义监控客户端服务器登录的人数 需求&#xff1a;限制登录人数不超过 3 个&#xff0c;超过 3 个就发出报警信息 1.在客户端创建自定义key //明确需要执行的 linux 命令 who | wc -l//创建 zabbix 的监控项配置文件&#xff0c;用于自定义 key vim /etc/zabbix/zabbix_ag…

零基础入坑Python爬虫的全面学习指南

文章目录 首先爬虫是什么&#xff1f;1. Python学习2.Python urllib和urllib2 库的用法3.Python 正则表达式4.爬虫框架Scrapy爬虫基本原理关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工…