malloc内存分配与free内存释放

        这里的存储分配程序,讲的就是标准库中malloc函数的实现原理。首先要了解针对malloc的内存存储结构。malloc不像全局变量一样,不是在编译器编译的时候就会分配内存空间,而是在调用到malloc函数时才会分配空间。有时还会中途调用free函数释放空间出来。所以:

        1、malloc在第一次被调用时,从系统中获取最小为一个单元的空闲空间(eg:最小单元为1024个最受限单元块。当x<=1024,获取1024个,否则获取x个),再进行分配;

        2、malloc所剩下的空闲空间一般都不是连续的,而是分散的。这样也提高了空间的利用率。

        为了管理malloc的空闲空间,每一个独立块的最前面都包含了一个“头部”信息:一个指向下一个空闲块的指针、一个本身独立块的长度(书上说还有一个指向自身存储空间的指针,但每个存储空间都有自身的指针,为什么还要这个呢。后看英语版原著,这么写的:Each block contains a size, a pointer to nextblock, and the space itself.)。下一个空闲块是按存储地址升序排列,离本空闲块最近的一个空闲块,若本空闲块在最后,则指向最前的空闲块。这样所有属于malloc的空闲空间都被串在了一起。如下图所示:



        因为后面的free函数已经把相邻的空闲链表给整合成一块了,所以我的图没有出现相邻的空闲链表。

        每块由malloc控制的空间都包含一个“头部”信息,为了方便管理,每块的空间大小都是头部大小的整数倍。而头部长度=指向下一个空闲块的指针的长度+自身空间大小的unsigned长度。但为了确保由malloc函数返回的存储空间满足将要保存的对象的对齐要求。每个机器都有一个最受限的类型:如果最受限的类型可以存储在某一个特定的地址中,则其他所有的类型也可以存放在此地址中。有的是double型,有的是long型,甚至还有的是int型。因此,头部结构将与最受限的类型进行联合,来确保对齐。

        因为有头部信息,头部信息里的本块空间size也是包括头部的大小,所以每次申请malloc空闲块的时候,都要加上一个单元,最后返回给用户的时候,再去掉头部。

        每次调用malloc申请空间时,malloc有一个专门指向当前空闲块链表的静态指针freep。从当前开始扫描剩下的空闲块链表,直到扫到一个足够大的空闲块。此算法成为“首次适应”(first fit),与之相对的是“最佳适应”(best fit):它将扫描出满足条件最小的块。这里的代码是“首次适应”算法。结果将出现三种情况:

        1)找到一块刚好合适的空闲块,则此块空间从链表中移走并将此块的地址返回给用户,并把静态指针freep指向前一空闲块地址;

        2)找到一块比需求大的空闲块,则从此空闲块中的后部取一块与需求一样的空间给用户,前部改变空闲块大小便可;


注(直到写本博文才发现自己错了):

①一直都认为返回给用户地址前一单元的头部,应该把空间退还给前面的空闲块,不然就闲着了。其实,里面记录了一个重要信息:空间块大小(包括头部和返回给用户的单元大小),在free释放空间的时候,就必须用到此头部的信息;

②后面的free程序以为是专供系统申请空间后插入空闲块链表用的,其实它就是我们平常用malloc、realloc、或calloc申请空间后,再释放的程序。

        3)如果扫描了一遍,都没有找到足够大的空闲块,则向系统再申请一块新的空间。

        上面都是在malloc已经有了空闲块的前提下,但第一次申请的时候,malloc是没有空闲块空间的。因此,在预编译时,就建立了一个单元的空闲块链表base来当做空闲链表的入口。当第一次调用malloc时,空闲链表的静态指针freep为NULL,那将它指向base,大小设为0(这样这块base空间将一直存在,且不被申请,确保了之后freep一直指向有效的空闲块链表),且指向它自己,同时向系统申请空闲空间(每次向系统申请的空间都是一块连续的空闲块)。

[cpp]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. typedef long Align; /*按照long类型的边界对齐,即以long作为最受限类型*/  
  2. union header{   /*头部信息*/  
  3.     struct {  
  4.         union header *ptr;  /*指向下一个空闲块*/  
  5.         unsigned size;      /*本空闲块大小*/  
  6.     }s;  
  7.     Align x;    /*强制对齐*/  
  8. };  
  9. typedef union header Header;  
  10.   
  11. static Header base; /*第一次调用malloc的空闲块链表入口,大小为0的空链表(按照上面逻辑的来说,这里的size应该为1)*/  
  12. static Header *freep = NULL;    /*静态的空闲块链表指针,初始化为NULL。第一次申请后才会指向base*/  
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值