首页 > malloc为什么会报错:memory corruption

malloc为什么会报错:memory corruption

最近遇到一个问题,很有意思,在此记录下,以备后续参考。

程序运行异常,报错:malloc: memory corruption.

用gdb 调试程序,bt 如下,程序在申请344 bytes内存时失败。

疑问:344bytes内存并不大,为何会失败呢?

进一步,打开AddressSanitizer,重选编译并运行程序,AddressSanitizer报错如下,报错内容分3部分贴出如下(信息安全,隐藏掉部分堆栈信息):

1. 重点:红色字体:heap-buffer-overflow on address 0xf3805ef0, 蓝色字体, WRITE of size 4 at 0xf3805ef0

解释:堆溢出,在*.c的211行对0xf3805ef0地址非法写,尝试写4个byte.

2.绿色字体:0xf3805ef0 is located 192 byte to the right of 688-byte regin [0xf3805b80,0xf3805e30)

 在*.c的507行分配了688个byte - 对应内存区域[0xf3805b80,0xf3805e30), 程序非法访问的地址0xf3805ef0 位于此内存区域右侧的192个byte的位置。

3. Summary.

分析过程不必赘述,我把结论写一下:

1.  在*.c的507行分配了688个byte - 对应内存区域[0xf3805b80,0xf3805e30)

    分析code, 发现这里是分配了2个结构体struct M,sizeof(struct M) = 344.    

typedef struct M
{...int data;...
} M_t

2.  在*.c的211行对0xf3805ef0地址非法写,尝试写4个byte.

   查看code,在211行尝试写一个struct M的成员data, 而data成员之前结构体成员的长度为192.

 

注意cellGroupId的offset 和 size.

 

回味下面ASAN的提示:

0xf3805ef0 is located 192 byte to the right of 688-byte regin [0xf3805b80,0xf3805e30)

由此可以推测:程序动态分配了2个struct M, 由于code 存在bug, 却访问了第三个struct M. 

最后进一步debug,发现程序确实是指针操作出错,访问了2个struct M后面的内存。

思考:malloc失败 与 AddressSanitizer: heap-buffer-overflow

没有开启AddressSanitizer时,程序写struct M的成员data时并没有直接报错,而是延迟到再次malloc内存时报错?

个人认为如下:

1. 程序非法写struct M的成员data,0xf3805ef0  地址位于堆上,此地址是可写的。(如果是访问.text代码段地址的话,程序是会马上终止的。)

2. malloc时,我推测内存管理模块会check将要分配出的内存区域是否正常。 怎么检查:比如,没有分配出的内存区域设置为默认值或者魔数,如果发现有其它的非法值存在,就发生了非法写,也就是说此内存还没有被分配出去,就已经有code 对其做了写操作。

根据之前内存池管理(https://blog.csdn.net/wowricky/article/details/83218126)的经验, 内存管理模块会在malloc和free时对内存区域进行检查,如果存在异常会直接报错memory corruption。所以malloc时的内存报错,通常是由于之前的内存越界访问导致的,这种问题通常比较难以定位。我碰到的这个问题比较幸运,非法访问地址0xf3805ef0  是前一个动态内存区域[0xf3805b80,0xf3805e30) 操作不当导致的。

  

更多相关:

  • 更多内容,欢迎关注微信公众号:全菜工程师小辉~前言在笔者上一篇博客,详解了NIO,并总结NIO相比BIO的效率要高的三个原因,彻底搞懂NIO效率高的原理。这篇博客将针对第三个原因,进行更详细的讲解。首先澄清,零拷贝与内存直接映射并不是Java中独有的概念,并且这两个技术并不是等价的。零拷贝零拷贝是指避免在用户态(User-space)...

  • 一、预备知识—程序的内存分配  一个由c/C++编译的程序占用的内存分为以下几个部分  1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈,如果还不清楚,那么就把它想成数组,它的内存分配是连续分配的,即,所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器...

  • 我的爱机是一台ThinkPad T420,原装三星DDR 1333 4G内存一根,还剩一根内存位置,最近趁京东6.18促销,准备增加一根物理内存。为了确保兼容性,觉得仍然选购DDR 1333 4G内存,于是购买了金士顿这款,比如DDR3 1600的还贵。 这个安装过程完全参照该内存的网页提示进行 这里简单记录一下,以备...

  • 陪伴我多年的老本ThinkPad T420渐渐垂垂老矣, 我想更新一下可以更新的部分, 比如将2.5寸HDD更换为SSD, 将单条4G内存再增加一根, 凡此种种想法, 可能最后归结为如何获取该笔记本的硬件配置信息, 在windows下面使用鲁大师之类的检测软件, 也许很好搞定,但是在Ubuntu 14.04平台上如果办到呢? 很简单...

  • 一.内存错误出现的场景 这几天在重构ATS插件代码的过程中遇到了烦人的内存泄露问题, 周五周六连续两天通过走查代码的方法,未能看出明显的导致内存错误的代码, 同时也觉得C和C++混合编程得到一个动态库, 在一个.cpp主文件中,即用new又用malloc来动态分配内存, 可能会导致内存错误.后来网上调研和查资料发现, new和mal...

  • 最近公司要做一个企业微信的小程序,方便企业内的成员来登录,以便一些公司内的业务,只限于公司内的成员来操作,因为有微信小程序的开发经验,所以先当作微信小程序来开发了!首先来讲一下这个企业微信小程序与微信小程序登录的不同,下面是微信小程序登录的流程:小程序内需要调用wx.login(),获取临时登录凭证code,并回传到开发者服务器,然后...

  • sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可以看作是一个列表,所以才能用[]提取其中的元素。其第一个元素是程序本身,随后才依次是外部给予的参数。下面我们通过一个极简单的test.py程序的运行结果来说...

  •   标题:创意虾-程序纹理Blender大师班 信息: 什么是程序纹理? 程序纹理将简单的数学转换为无限的真实感着色器,具有无限的多样性和分辨率。 超越看起来像一团像素特写的图像纹理,运用程序纹理的力量,清晰的细节和没有重复的模式。 你是不是在玩节点滑块,得到了一些有趣的结果,但不确定引擎盖下到底发生了什么?掌握了节...

  • gprof用于分析函数调用耗时,可用gprof分析最耗时的函数,以便优化程序。 gcc链接时也一定要加-pg参数,以使程序运行结束后生成gmon.out文件,供gprof分析。 gprof默认不支持多线程程序,默认不支持共享库程序。 gcc 编译程序时添加编译选项-pg 运行程序,程序退出时生成 gmon.outgprof ./...

  • 一.虚拟机、linux简介 简单介绍一下虚拟机还有就是各种操作系统,比如centos,Ubuntu 操作系统:linux(centos、Ubuntu、redhat),Android,Windows(xp、win8、win10) 进程,多个程序,分时技术,并行技术 一次打开多个程序,我们在只有一个cpu,如何让这些程序进...