malloc为什么会报错:memory corruption

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

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

malloc为什么会报错:memory corruption_第1张图片

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

malloc为什么会报错:memory corruption_第2张图片

疑问: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.

malloc为什么会报错:memory corruption_第3张图片

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

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.

 malloc为什么会报错:memory corruption_第4张图片

回味下面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) 操作不当导致的。

  

你可能感兴趣的:(Developer,Quality,Linux/HPUX,gcc/gdb编译调试,segmentfault,指针,内存管理)