教训:malloc之前确认malloc的长度是否为0

版权声明:本文为博主原创文章,未经博主允许不得转载。转载请注明出处:http://blog.csdn.net/neuq_jtxw007 https://blog.csdn.net/neuq_jtxw007/article/details/79867911

教训:malloc之前确认malloc的长度是否为0

导致问题:segment fault段错误的问题,这种问题很难寻找,所以要避免malloc(0),如果出现类似问题可以二分法加打印定位问题点。

问题分析:

  初始化在堆上malloc了一块区域,但是malloc()的size为0,这块地址被用来存了很多数据,数据依然可以使用,但是存的数据会将其他地址踩掉,就会在用其他地址的时候存在segment fault段错误问题

关于malloc(0)

  在标准的malloc实现中,并不检查输入值的大小,而是将输入值做对齐操作后直接从堆上分配空间。
  不论输入值的大小为多少,在malloc的内部最小的内存分配大小是一个定值(一般是8B),因为malloc需要用这部分空间来维护堆上的内存块链表。所以当用户申请一块0B的空间时,malloc实际分配的空间是8B,如果用户申请的空间是X,则malloc实际分配的空间是(对齐(X)+8)。这也是为什么malloc分配的空间千万不能越界使用的原因:堆的内部链表结构将被破坏。
  
  对于new和delete malloc和free这样的内存分配与释放函数:到底delete和free是怎么知道要释放掉多少内存的呢?
  其实在new和malloc内存分配成功时,系统除了返回一个指向这块内存的指针外,还会获得一块用于记录此处分配的内存大小的内存块
  
  在内存管理中,内存被分为两部分:栈和堆。
  栈有自己的机器指令,是一个先进后出的数据结构。
  malloc分配的内存是堆内存,由于堆没有自己的机器指令,所以要有系统自己编写算法来管理这片内存,通常的做法是用链表,在每片被分配的内存前加个表头,里面存储了被分配内存的起始地址和大小,你的malloc返回的就是表头里的起始指针,这个地址是由一系列的算法得来了,通常不会为0,一旦分配成功,就返回一个有效的指针,对于分配0空间来说,算法已经算出可用内存的起始地址,但是你占用0空间,所以对那个指针操作就是错误的,操作系统一般不知道其终止地址,因为有占用大小就可以推出终止地址,还有就是即使分配0空间也要释放它,其实是释放的链表结点。

sample

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char* temp = NULL;
    temp = malloc(0);
    printf("the address of temp = %p\n", temp);
}

输出结果:

the address of temp = 0x685010

说明malloc(0)是会返回malloc的地址,只是malloc的地址长度为0

猜你喜欢

转载自blog.csdn.net/neuq_jtxw007/article/details/79867911