访问0xdddddddd内存地址引发软件崩溃的实战问题排查

news2024/11/17 16:16:55

目录

1、问题描述

2、访问空指针或者野指针

3、C++程序中常见的异常内存值

4、0xdddddddd内存访问违例问题分析与排查

4.1、初步分析

4.2、CConfMeidaConfigDlg窗口类对象是何时被销毁的?

4.3、为啥会访问到已经释放内存的CConfMeidaConfigDlg类对象?

5、关于0xcdcdcdcd和0xfeeefeee异常值的排查案例

6、最后


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.htmlWindows C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.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       在C++软件中访问了有问题的指针变量,可能会引发程序产生异常,比如访问了空指针和野指针,这也是操作指针错误最常见的原因。今天我们就来讲一个操作已经释放内存的野指针实例,本例中的问题指针有些特殊,释放内存后指针值变为0xdddddddd,和以往常见的异常值0xfeeefeee有所不同。本文将详细讲述一下这个问题的完整分析过程,以供大家借鉴或参考。

1、问题描述

       某天在调试某个功能时发现,在执行某个操作(为了方便说明问题,下文将该操作称作A操作)后再次执行该操作,程序就出现了短暂的卡死,然后出现了闪退。这个问题是必现的,于是用Visual Studio调试运行,按照复现的步骤复现了问题,弹出了如下的访问0xdddddddd异常内存地址的弹框:

对于32位程序,这个0xddddddddd地址属于内核态的内存地址,用户态的代码是禁止访问的,所以触发了内存访问违例,产生了崩溃。下面就详细讲述一下这一问题的排查过程。

2、访问空指针或者野指针

       在操作指针时,最常见的问题就是访问空指针和野指针。操作这两类指针产生的异常,均是因为使用该指针去访问了指向类对象的数据成员(把指针中存放的地址作为类对象首地址去访问),访问了不该访问的内存地址,引发了内存访问违例。对于空指针,在使用空指针访问了类对象的数据成员,就会访问很小的内存地址,小于64KB地址值的内存区域是禁止访问的。

       产生野指针,主要有两个场景

1)Release下没有对指针变量进行初始化,指针变量的值是个随机值,是分配内存时内存中残留的随机值,此时的指针就是野指针。
2)指针指向的内存被释放了,但指针没有置为NULL,此时的指针也是野指针。

通过野指针中的值去访问指向类的数据成员,也会触发访问不该访问的内存地址,触发内存访问违例,引发崩溃。 

3、C++程序中常见的异常内存值

       在讲述这个问题排查过程之前,需要先讲一下C++程序中常见的异常内存值,这了解这些异常内存值之后,可能就能知道是什么原因引发的,这样就给我们排查问题指明了方向。所以作为Windows C++开发人员,很有必要去了解这些常见的异常地址。

       C++程序中常见的异常内存值,如下所示(异常值不区分大小写,比如0xcdcdcdcd也可以写成0xCDCDCDCD):

* 0xcccccccc:Used by  Microsoft's C++ debugging runtime library and many DOS environments to mark uninitialized stack memory.CC resembles the opcode of the  INT 3 debug breakpoint interrupt on x86 processors.
* 0xcdcdcdcd:Used by  Microsoft's C/C++ debug malloc() function to mark uninitialized heap memory, usually returned from HeapAlloc().
* 0xfeeefeee:Used by  Microsoft's debug HeapFree() to mark freed heap memory. Some nearby internal bookkeeping values may have the high word set to FEEE as well.
* 0xdddddddd:Used by MicroQuill's SmartHeap and Microsoft's C/C++ debug free() function to mark freed heap memory.
* 0xabababab:Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory.
* 0xabadcafe:A startup to this value to initialize all free memory to catch errant pointers.
* 0xbaadf00d:Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory.
* 0xbadcab1e:Error Code returned to the Microsoft eVC debugger when connection is severed to the debugger.
* 0xbeefcace:Used by Microsoft .NET as a magic number in resource files.

       这里我们主要关注0xcccccccc、0xcdcdcdcd、0xfeeefeee和0xdddddddd这四个异常内存值。这几个异常地址都是Debug下默认设置的,0xcccccccc用来填充未初始化的栈内存,0xcdcdcdcd用来填充未初始化的堆内存,0xfeeefeee用来填充已经释放的堆内存,0xdddddddd也是用来填充已经释放的堆内存。

0xfeeefeee和0xdddddddd都是用来填充已经释放的堆内存区域,但不太清楚这两个异常值的区别。我们经常在调试代码遇到0xfeeefeee,基本很少遇到过0xdddddddd,本案例还是第二次遇到0xdddddddd。

      我们需要对这些异常内存值有较强的敏感度,如果在调试代码中遇到这些异常值,要第一时间反应过来,通过这些异常内存值的含义,可以明确地提示我们当前访问的内存大概出了什么问题。这样我们排查时就有了一定的方向。

4、0xdddddddd内存访问违例问题分析与排查

       根据异常中断时的弹窗提示,当前访问了异常内存值0xdddddddd:

通过这个异常值的含义大概知道可能是访问了已经释放内存的野指针引发的。

       0xdddddddd异常值提示我们程序中访问了已经释放的内存区域,那我们需要去分析这块内存是何时释放的,以及为什么会出现访问已释放内存的问题。可以结合当前的函数调用堆栈,结合代码上下文的逻辑,大概就能分析出原因了。

4.1、初步分析

       根据Visual Studio中断的代码位置:

问题发生在COptionUI::Selected函数中,当前函数中的this指针值为0xddddddddd,即当前的COptionUI类对象的地址为0xddddddddd,通过该类对象地址去访问该类的数据成员m_bSelected产生了异常,数据成员m_bSelected的内存地址就是相对所在类的类对象首地址的偏移,是个内核态的内存地址,所以出现了内存访问违例,产生了崩溃。

       我们需要搞清楚当前出问题的COptionUI类对象位于那个具体的业务类中。沿着此时的函数调用堆栈,双击截图中的条目:

可以看到是CConfMeidaConfigDlg窗口类中的m_pBtnNotShow按钮控件指针的值为0xddddddddd,如下:

根据0xddddddddd的含义,是用来填充已经释放的堆内存的,所以基本可以确定m_pBtnNotShow所在的CConfMeidaConfigDlg类对象已经被delete了,即CConfMeidaConfigDlg类对象的内存被销毁了!


       在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:(该精品技术专栏的订阅量已达到430多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

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

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

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2:  

C++常用软件分析工具从入门到精通案例集锦汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795

常用的C++软件辅助分析工具有PE工具、Dependency Walker、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题,很有实战参考价值!

专栏3: 

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

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

专栏4:   

VC++常用功能开发汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

将10多年C++开发实践中常用的功能,以高质量的代码展现出来。这些常用的高质量规范代码,可以直接拿到项目中使用,能有效地解决软件开发过程中遇到的问题。

专栏5: 

Windows C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.html

根据多年C++软件开发实践,详细地总结了Windows C++ 应用软件开发相关技术实现细节,分享了大量的实战案例,很有实战参考价值。


4.2、CConfMeidaConfigDlg窗口类对象是何时被销毁的?

       首先要搞清楚CConfMeidaConfigDlg类对象是何时被销毁的。很简单,我们直接在CConfMeidaConfigDlg类的析构函数中打个断点,复现一下问题,就知道了。

       在CConfMeidaConfigDlg类的析构函数中打了断点,然后重新启动调试,然后执行第一次操作,操作完成后命中了断点,如下所示:


查看此时的函数调用堆栈,是某个窗口消息触发CConfMeidaConfigDlg类对象销毁的。于是双击收发窗口消息的函数条目,进入函数:

是代码中给CConfMeidaConfigDlg窗口发送了WM_CLOSE,然后duilib框架将窗口类对象delete了。

4.3、为啥会访问到已经释放内存的CConfMeidaConfigDlg类对象?

       相关代码是其他同事写的,于是查看了代码的上下文逻辑,在软件执行当前的A操作时会去创建这个CConfMeidaConfigDlg窗口类:

但操作结束后并不会去销毁这个窗口,而是保存在成员变量中,下次再次执行当前的这个A操作时继续使用。

       但第一次执行A操作时,操作结束后CConfMeidaConfigDlg类对象就被销毁了,这个和原有的逻辑就不一致了。于是搜索WM_CLOSE消息,看看哪里给CConfMeidaConfigDlg窗口类发送了WM_CLOSE,然后找到了问题代码:

是这个地方发送了WM_CLOSE消息,后面还专门有个注释,于是查看svn的修改记录,原先是发送WM_UPDATE_CTRL_WINDOW消息,被一个同事改成了发送WM_CLOSE消息。这个同事有点不负责啊,没搞清楚代码的逻辑,就随意地修改了!

       上述代码在A操作动作结束后会被调用到,给CConfMeidaConfigDlg窗口类发送了WM_CLOSE消息,导致CConfMeidaConfigDlg窗口被销毁,CConfMeidaConfigDlg窗口类对象被析构(析构后会将原先分配给CConfMeidaConfigDlg对象的内存区域置为0xdddddddd),但存放CConfMeidaConfigDlg类对象地址的指针变量m_pConfMeidaConfigDlg并没有置空,指针变量中还是之前的类对象指针,这个指针就变成了野指针。

       再次执行A操作时,判断m_pConfMeidaConfigDlg指针变量不为空,就直接使用这个指针了,从而访问了野指针,从而出现访问0xdddddddd导致内存访问违例,引发崩溃的问题。

       解决办法很简单:

将上述代码中的WM_CLOSE改成之前的WM_UPDATE_CTRL_WINDOW消息即可

5、关于0xcdcdcdcd和0xfeeefeee异常值的排查案例

       关于常见异常内存值0xcdcdcdcd、0xfeeefeee和0xdddddddd的排查案例,可以参见我之前写的文章:
0xcdcdcdcd异常值引发C++程序崩溃问题的详细分析icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/128380751排查软件启动时访问了0xcdcdcdcd内存地址导致内存访问违例的崩溃icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125266735排查软件关闭时访问了0xfeeefeee内存地址导致内存访问违例的崩溃icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125267046访问0xdddddddd内存地址引发软件崩溃的问题排查icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/132631020

6、最后

       大家在调试代码要提高对0xcccccccc、0xcdcdcdcd、0xfeeefeee和0xdddddddd等常见异常内存值的敏感度,看到这些异常值就能大概地估计是什么原因导致的,这样我们就有了问题排查的方向。此外,在设置断点也要有一定的技巧,比如使用数据断点监测内存越界问题、人为添加if条件语句构造“条件”断点、在命中一个断点后再设置后续断点等等。

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

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

相关文章

centOS Stream9配置NAT8网络

首先将VMware关机,添加网络适配器 启动虚拟机,查看ens192是否打开连接 安装的图形化需要查看右上角电源处网卡是否连接 最小化安装一般不会出现未连接的状态 使用ip a 查看 配置网卡文件 cd /etc/NetworkManager/system-connections/cd到当前目录下…

四维世景产品及研发部副总经理张静普受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 四维世景科技(北京)有限公司产品及研发部副总经理张静普先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“项目管理中的数字化实践及应用”。大会将于6月29-30日在北京举办,敬请关注…

C++11(下):线程库

线程库 1.线程1.1线程类介绍以及简单使用1.2线程函数参数1.3如何获取线程函数返回值 2.锁2.1锁的种类2.2 lock_guard与unique_lock 3.原子库3.1介绍与基本使用3.2CAS(原子操作原理) 4.条件变量 1.线程 1.1线程类介绍以及简单使用 在C11之前&#xff0c…

Android device/xxx/system/common/overlay编译产物

MTK 如下代码编译的产物在 framework-res.apk 编译配置文件在device/mediatek/system/common/目录下的Android.bp device/mediatek/system/common/overlay/telephony/frameworks/base/core/res/res/values-mcc655-mnc01/config.xml 在Android U上面还在overlay目录中进行了产…

NSSCTF-Web题目10

目录 [强网杯 2019]随便注 1、题目 2、知识点 3、思路 [GXYCTF 2019]BabyUpload 1、题目 2、知识点 3、思路 [强网杯 2019]随便注 1、题目 2、知识点 数据库注入,堆叠注入,更改表名 3、思路 正常提交查询,看看数据回显 加入单引号…

Ubuntu下FastDDS的源码编译和简单测试

FastDDS是eprosima公司开发的DDS(Data Distribution Service)库,使用的语言是C,自称是"The Most Complete Open Source DDS Middleware",其官网是https://eprosima.com/,FastDDS源码在https://gi…

金鸣识别系统:PDF转Excel的高效利器

在日常办公中,我们经常需要将PDF文档转换为Excel表格以便进行数据分析。然而,当有些PDF转换过程可能会变得复杂,因为许多转换工具无法完美处理图片元素,导致转换后的准确率不高或排版错乱。幸运的是,金鸣识别系统以其卓…

细致解析跨境电商多平台搭建利器-179海关接口源码应用方法

介绍 跨境电商已成为当前电商行业的热门发展方向之一。为满足跨境电商的需求,各大平台纷纷推出了多平台搭建利器。其中,179海关接口源码是一款非常实用的工具,本文将对其应用方法进行细致解析。 了解179海关接口源码 179海关接口源码可以帮…

天翼云8080、80端口用不了的问题

天翼云8080、80端口用不了的问题 前言:前段时间天翼云搞了活动,原来公司用的华为云老板说太贵了也快到期了,就换了天翼云的服务器。 排查: 安全组开放 80 8080 防火墙查看 没有问题 nginx nacos dcoker等停了 查看监听端口 发现…

回答网友的一个DBGrid的问题

起因 网友在QQ群里问Text字段的显示问题。 俺回答:百度了一下 方法有 很多很多 。然后给他百度了6种方案。然后告诉他找个顺眼的用。 可是,对方感觉都顺眼。俺就新写了一个 。 代码 创建测试数据 begin ADODataSet1.DisableControls; colcnt:5; …

git 基本命令

列出分支基本命令: git branch 如果我们要手动创建一个分支 。执行 git branch (branchname) 即可: git branch testing 切换到testing分支: git checkout testing 我们也可以使用 git checkout -b (branchname) 命令来创建新分支并立…

斯巴达(Spartanhost)VPS的性能评测

原创原文链接:详细斯巴达(Spartanhost)VPS的性能和购买价值评测 | BOBO Blog (soulcloser.com)https://www.soulcloser.com/3398/ 引言 最近看了全球的VPS商家,想搞台网站高性能的服务器,发现一个特别有意思的商家竟…

反激开关电源整流桥选型及计算

整流桥的作用就是把输入交流电压整形成直流电压,把正弦波整成馒头波,由于整流管的单向导电 性,在输入电压瞬时值小于滤波电容上电压时整流桥,在这个时候是不导通的,使整流桥的电流变 成2-3ms左右的窄脉冲。为获得所需…

深信服终端安全管理系统EDR版本升级过程

EDR当前版本为3.7.12,具体参考版本详情参数。需要升级到6.0.2R1版本,该版本更改了产品名称,叫做“统一端点安全管理系统aES” 当前版本详情 版本基础信息 软件版本:3.7.12.3829 病毒库版本:20240618174426 漏洞规则库&…

在金仓数据库中导入sql文件,解决中文数据乱码问题

先确定数据库服务端编码方式是UTF8,如果不是,那就先解决这个问题。操作:当连接数据库之后,执行show server_encoding 用Notepad打开,目的:确定文件编码是UTF-8格式 在sql文件前面加上set NAMES utf8; …

为什么AC/DC线性电源的体积大?

电源按照转换原理分类,可分为线性电源和开关电源。线性电源和开关电源的特点如下: 1、线性电源的调整管工作在放大状态,因而发热量大,效率低(与压降多少有关),需要加体积庞大的散热片。实现交流…

第6章 设备驱动程序(3)

目录 6.5 块设备操作 6.5.1 块设备的表示 6.5.2 数据结构 6.5.3 向系统添加磁盘和分区 6.5.4 打开块设备文件 本专栏文章将有70篇左右,欢迎关注,查看后续文章。 6.5 块设备操作 特点: 随机访问任意位置。 固定块大小的传输。 块设备在内…

探究 IP 地址被网站封禁的原因

在我们登录各种网站、APP浏览时,可能会遇到 IP 地址被某些网站封禁的情况。很多人奇怪这是为什么呢? 首先,违反网站的使用规则是比较常见的原因之一。比如,频繁发送垃圾邮件、恶意评论、进行网络攻击或试图破解网站的安全机制等不…

邻氯苯甲酰氯在医药、农药等领域应用广泛 市场需求稳定且有增长趋势

邻氯苯甲酰氯在医药、农药等领域应用广泛 市场需求稳定且有增长趋势 邻氯苯甲酰氯又称为2-氯苯甲酰氯、氯化邻氯苯甲酰,化学式为C7H4Cl2O,是一种化学物质,外观为黄色液体,不溶于水,溶于醇、醚、丙酮,有强烈…

调度算法-进程调度算法

发⽣ CPU 调度通常有以下情况: 1. 当进程从运⾏状态转到等待状态;2. 当进程从运⾏状态转到就绪状态;3. 当进程从等待状态转到就绪状态;4. 当进程从运⾏状态转到终⽌状态 常⻅的调度算法: 先来先服务调度算法最短作业…