Release库与Debug库混用导致释放堆内存时产生异常的详细分析

news2024/11/16 17:27:46

目录

1、问题描述

2、使用Windbg启动Debug版本的exe程序进行分析

3、进一步分析

4、问题复盘

5、为什么Debug库与Release库混用可能会出异常?

6、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931       Debug和Release版本的库,在内存管理和实现机制上是有差异的,所以一般情况下Debug版本的库是不能和Release版本库混用的,如果混用则可能会产生一些异常。今天我们讲述一个因为Debug库与Release库混用引发的异常崩溃问题实例,以供大家借鉴或参考。

1、问题描述

       我们的软件产品相对比较复杂,从上到下包含了上百个模块,新人需要搭建Debug编译及调试运行环境。手动将底层模块的.lib库(编译时使用)和.dll库(运行时要加载)拷贝到项目代码目录中,然后编译主工程所依赖的多个工程,最后将exe主工程程序给运行起来。结果用Visual Studio刚将主工程启动起来就遇到了崩溃,弹出了如下的崩溃提示框:

       这是个Debug断言错误,是在调用_CtrlsValidHeapPointer系统函数时产生的断言,估计是在对某个堆内存执行操作时产生了异常。于是切换到call stack页面,查看到如下的函数调用堆栈:
从调用堆栈得知,在delete释放堆内存时产生了异常,但VS中显示的堆栈中只能看到模块名,看不到具体的函数。

       最开始我们没想到是Release版本库与Debug版本库混用导致的,只能一步一步向后分析。

2、使用Windbg启动Debug版本的exe程序进行分析

       既然VS中看不到有效的函数堆栈,于是想到使用Windbg去分析一下。因为程序在启动时就崩溃了,所以需要使用Windbg去启动目标exe程序。在Windbg中点击菜单栏中的File -> Open Executable...,弹出打开exe文件的提示框:


找到要启动的目标进程的路径,打开之即可。

       启动后,Windbg捕获到了异常,中断了下来,于是使用kn命令查看此时的函数调用堆栈。从堆栈中可以看到异常是mtpbstructdll.dll的某个函数触发的,于是使用lm vm xxpbstructdll*命令查看该库的时间戳,如下:

通过该二进制的时间戳得知,该库是2022年11月28日12点08分17秒生成的,于是通过该时间点到版本服务器上找到对应时间点的pdb文件,然后将pdb文件的路径设置到Windbg中,然后重新输入kn命令才看加载pdb文件后的详细的函数调用堆栈,如下所示:

调用堆栈中显示了详细的函数名和行号,其中从第9帧中显示的信息:

09 004eaa44 5c6c5158 xxpbstructdll!google::protobuf::RepeatedPtrField<mt::TMTSingleSysPathPrefix>::~RepeatedPtrField<mt::TMTSingleSysPathPrefix>+0x54 [k:\cbb\xxcomponent\git\xxcomponent_soft\10-common\include\thirdparty\google\protobuf\repeated_field.h @ 1020] 

可以看出是在RepeatedPtrField类析构时触发了delete去释放堆内存,最终导致了异常。这个RepeatedPtrField类位于thirdparty\google\protobuf\repeated_field.h头文件的1020行,估计RepeatedPtrField类是模板类,其实现是放在头文件中的。

       xxpbstructdll库中定义了很多protobuf结构体,并实现C++结构体与protobuf结构体的转换,主要是通过protobuf可以将C++结构体中的数据进行序列化。这个mtpbstructdll.dll库好久都没改动了,如果有问题,早就应该暴露出来了。并且Release版本的安装包安装后是可以正常运行的,这就奇怪了。

3、进一步分析

       于是沿着函数调用堆栈继续向上看,是调用组件的XXX_SetSysWorkPathPrefix函数触发上述问题的,调用该函数的上下文代码是用来初始化底层库的,并且XXX_SetSysWorkPathPrefix是调用底层库的第一个接口!第一个接口就报错了,说明还是库有问题啊!

       听维护xxpbstructdll.dll库的同事说,mtpbstructdll.dll库还依赖了protobuf.dll开源库。新人搭建的是Debug下的运行环境,难道是Release库与Debug库混用导致好的?于是问新人,protobuf.dll库是从哪里拷贝过来的,他说在他的系统中直接搜索protobuf.dll文件,是从一个Release路径下拷贝过来的,这就对了,Release版本的protobuf与Debug库混用了,肯定是混用引发的问题。于是让其从某个Debug目录中拷贝一个protobuf.dll文件过来,然后运行就没问题了。

4、问题复盘

       为啥protobuf.dll库会出现这样的问题,而其他dll库没有这样的问题呢?是因为这个protobuf.dll库有点特殊,只给我们代码流发布了release版本的库,没发布debug版本的库,所以在Debug下启动运行时报如下的错误:

提示程序启动时找不到protobuf.dll库,于是同事使用Everything工具在机器上搜索了一下protobuf.dll库,于是就找到了上面说到的一个release版本的protobuf.dll库,拷贝到Debug目录中,所以就出现了release库与debug库混用的场景,导致本例中异常的发生。

5、为什么Debug库与Release库混用可能会出异常?

       至此,可以确定是Release版本的protobuf.dll与其他Debug版本库混用导致的。那为什么Debug库与Release库混用可能会出异常呢?因为Debug版本与Release版本的内存管理机制是不太一样的,Debug下编译器会给程序申请的内存多分配一些额外的内存,用来存放一些调试信息和桩信息,而在Release下是不会额外分配内存的,所以在释放堆内存时也要对应起来的,Debug下申请的堆内存要用Debug下的函数去释放,用Release下的函数去释放则会有问题。

        比如在Debug版本库中申请的堆内存,到Release库中去释放;Release版本库中申请的堆内存,到Debug版本库中去释放,都会出现内存释放异常问题。所以,一般情况下我们是严禁Release版本库与Debug版本库混用的,如果混用,可能会带来一些莫名其妙的内存问题。

6、最后

       本文讲述了一个因为Release库与Debug库混用导致内存释放时的异常崩溃问题,这是一个很有隐蔽性的错误,本文详细进行了相关的阐述,以给大家提供借鉴和参考。

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

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

相关文章

DM8:dexpdimp-逻辑导出--逻辑导入

DM8:dexp&dimp-逻辑导出--逻辑导入1 dexp逻辑导出dmp文件1.1 全库导出命令附加的参数信息1.2 导出用户所拥有权限的数据库对象-命令附加的参数信息1.3 导出用户所拥有权限的数据库对象-命令附加的参数信息2 dimp--逻辑导入dmp文件2.1 全库导入dmp数据文件-命令附加的参数信…

人体姿态估计-论文精读--DeepPose: Human Pose Estimation via Deep Neural Networks

图 1. 除了关节的极端变异性外&#xff0c;许多关节几乎不可见。我们能猜测左图中右臂的位置&#xff0c;因为我们看到了姿势的其余部分&#xff0c;并预测了这个人的运动或活动。同样&#xff0c;右边的人的左半身也根本看不见。这些都是需要进行整体推理的例子。我们相信DNNs…

php处理支付宝应用网关给接口发送的post参数

php如何接收支付宝应用网关发送的POST请求方式,参数又是GET请求的数据格式配置支付宝应用网关如何接收支付宝异步通知(应用网关接收请求)将&连接的参数分割成数组实例&#xff1a;难点配置支付宝应用网关 首先要在服务器上写一个接口,然后将接口的访问地址设置在支付宝应用…

手把手教Arthas,不再怕排查线上问题了

Arthas是alibaba开源的java诊断工具&#xff0c;支持jdk6&#xff0c;采用命令行交互模式&#xff0c;可以防败的定位和诊断线上的程序运行问题。官方文档&#xff1a;https://arthas.aliyun.com/doc/一、Arthas使用场景是否有一个全局视角来查看系统的运行状况&#xff1f;为什…

六种方式,教你在SpringBoot初始化时搞点事情!

前言 在实际工作中总是需要在项目启动时做一些初始化的操作&#xff0c;比如初始化线程池、提前加载好加密证书....... 那么经典问题来了&#xff0c;这也是面试官经常会问到的一个问题&#xff1a;有哪些手段在Spring Boot 项目启动的时候做一些事情&#xff1f; 方法有很多…

卷积层里的多输入多输出通道、池化层

多输入多通道每个通道都有一个卷积核&#xff0c;结果是所有通道卷积结果的和。无论有多少输入通道&#xff0c;到目前为止我们只用到单输出通道。可以有多个三维卷积核&#xff0c;每个核生成一个输出通道。输出通道数是卷积层的超参数。每个输入通道有独立的二维卷积核&#…

为什么JavaScript这么难学啊?

前言 觉得Js难其实是很正常的&#xff0c;首先这证明你在某些知识点上没有理解透彻&#xff0c;JS挺多的知识点点其实是比较抽象的&#xff0c;比如闭包、原型和原型链等&#xff0c;其次便是不会变通运用&#xff0c;这主要是敲代码熟练度的问题&#xff0c;所以我针对你这种…

架构运维篇(六):MySQL 8.0启用BinLog 支持

上一篇&#xff1a;架构运维篇&#xff08;五&#xff09;&#xff1a;Centos7/Linux中安装RocketMQ 最新线上的项目终于到多个数据执行的问题&#xff0c;找了团队DBA发现云上的MySQL 默认是没有启用BinLog支持。 小编研究了一下很简单&#xff0c;不过中间也遇到一些坑可以给…

结构重参数化(Structural Re-Parameters)PipLine

文章目录BASICSstrcutural Inception算法思想算法核心算法架构Re-Parameter四部曲&#xff1a;ACNetACNet原理ACNet分析涨点原因推理阶段融合机制Re-Parameter四部曲&#xff1a;RepVGGRepVGG原理RepVGG分析RepVGG BlockStructural Re-Parameters融合conv2d和BN融合1x1conv转换…

【一文讲通】样本不均衡问题解决--下

1欠采样、过采样欠采样&#xff1a;减少多数类的数量&#xff08;如随机欠采样、NearMiss、ENN&#xff09;。过采样&#xff1a;尽量多地增加少数类的的样本数量&#xff08;如随机过采样、以及2.1.2数据增强方法&#xff09;&#xff0c;以达到类别间数目均衡。还可结合两者做…

地址解析协议ARP

目录地址解析协议ARP1、流程2、动态与静态的区别3、ARP协议适用范围地址解析协议ARP 如何从IP地址找出其对应的MAC地址&#xff1f; 1、流程 ARP高速缓存表 当主机B要给主机C发送数据包时&#xff0c;会首先在自己的ARP高速缓存表中查找主机C的IP地址所对应的MAC地址&#xf…

Linux常用命令——lsblk命令

在线Linux命令查询工具 lsblk 列出块设备信息 补充说明 lsblk命令用于列出所有可用块设备的信息&#xff0c;而且还能显示他们之间的依赖关系&#xff0c;但是它不会列出RAM盘的信息。块设备有硬盘&#xff0c;闪存盘&#xff0c;cd-ROM等等。lsblk命令包含在util-linux-ng…

ES报文辅助生成工具-JavaFX

此程序为基于 Java8 开发的 JavaFX Maven 工程&#xff0c;是 Java 组装ElasticSearch请求报文工具的辅助 Java 代码生成工具&#xff0c;方便开发者快速编写代码。现学现用&#xff0c;写得不好。 工具界面 代码 pom.xml <project xmlns"http://maven.apache.org/P…

Android:URLEncoder空格被转码为“+”号

Android前段和后端接口交互时&#xff0c;经常会遇到特殊字符&#xff0c;比如表情、特殊标点等&#xff0c;这样在Url中是无法识别的&#xff0c;需要进行转码&#xff0c;后端进行解码交互。 但当使用URLEncoder时&#xff0c;会发现字符串中的空格被转换成“”号&#xff0…

客服系统即时通讯IM开发(四)网站实现实时在线访客列表【唯一客服】网站在线客服系统...

在使用我的客服系统时&#xff0c;如果引入了我的js &#xff0c;就可以实时看到网站上的所有访客了 使用 WebSocket 技术来实现实时通信。 在访客登录或退出时&#xff0c;向指定客服的 WebSocket 客户端发送消息。例如&#xff0c;你可以在访客登录时&#xff0c;向指定客服…

测试用例的设计? 万能公式

万能公式(必背)&#xff1a;功能测试性能测试界面测试兼容性测试易用性测试安全测试功能测试 &#xff1a;可能来自于需求文档&#xff0c;也可能来自生活经验性能测试 &#xff1a;功能没有问题不代表性能是ok的&#xff0c;性能往往体现在一些极端情况界面测试 &#xff1a;颜…

Prometheus-基于Consul的自动注册

一、背景介绍 如果我们的物理机有很多&#xff0c;不管是基于"file_sd_config"还是"kubernetes_sd_config"&#xff0c;我们都需要手动写入目标target及创建目标service&#xff0c;这样才能被prometheus自动发现&#xff0c;为了避免重复性工作过多&#…

【182】Java8利用二叉查找树实现Map

本文利用二叉查找树写了一个Map&#xff0c;用来保存键值对。 二叉查找树的定义 二叉查找树又名二叉搜索树&#xff0c;英文名称是 Binary Search Tree&#xff0c;缩写BST。 二叉排序树&#xff0c;英文名称是 Binary Sorted Tree&#xff0c;缩写BST。 二叉查找树、二叉搜…

excel实用技巧:如何构建多级下拉菜单

使用数据有效性制作下拉菜单对大多数小伙伴来说都不陌生&#xff0c;但说到二级和三级下拉菜单大家可能就不是那么熟悉了。什么是二级和三级下拉菜单呢&#xff1f;举个例子&#xff0c;在一个单元格选择某个省后&#xff0c;第二个单元格选项只能出现该省份所属的市&#xff0…

vue-router原理简单实现

vue-router简单实现 初步预习 动态路由 获取id方式 第一种强依赖路由 第二种父传子方式&#xff08;推荐&#xff09; 嵌套路由 相同的头和尾&#xff0c;默认index&#xff0c;替换为detail 编程时导航 this.$router.push() this.$router.repleace() this.$router.g…