dlmalloc解析连载二

前面连载提到过对于大小在256字节以下的chunk块是通过malloc_chunk组织管理的,256字节以下的chunk块一共有256/8=32类,即字节为8字节、16字节、24字节、32字节,……,256字节,因此dlmalloc维护32个双向环形链表(而且具有链表头节点,加头节点的最大作用就是便于对链表内节点的统一处理,即简化编程),每一个链表里的各空闲chunk块的大小一致,因此当应用程序需要某个字节大小(这里的字节大小是考虑了chunk块头和对齐等所占空间了的,即如果应用如果程序调用函数malloc(8),那么到dlmalloc这应该比8大,这种更细节的疑问下面还有,并非我故意不表达,只是转述太多了,倒说不清我自己真正想说的了,阅读时请读者自己注意就好)的内存空间时直接在对应的链表内取就可以了(具体稍有不同,即如果对应链表内没有空闲可用chunk块,则还会查看下一个链表,举个例子:当应用程序申请32个字节,如果32字节大小的链表为空,那么dlmalloc还会在大小为40字节的链表内查找空闲chunk块。),这样既可以很好的满足应用程序的内存空间申请请求而又不会出现太多的内存碎片。我们可以用如下图来表示dlmalloc256字节以下的空闲chunk块组织方式。

 

dlmalloc程序使用smallbins数组来记录这32个双向环形链表表头,该字段定义在结构体malloc_state内,在这里我们先不管malloc_state结构体而只关注smallbins这个字段,它的定义如下:

struct malloc_chunk {

  size_t               prev_foot;  /* Size of previous chunk (if free).  */

  size_t               head;       /* Size and inuse bits. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */

  struct malloc_chunk* bk;

};

 

mchunkptr  smallbins[(NSMALLBINS+1)*2];

其中,mchunkptr在上一篇已经提过,为“typedef struct malloc_chunk* mchunkptr;”,而空NSMALLBINS32,即是“#define NSMALLBINS (32U)”。因此smallbins为一个具有66malloc_chunk结构体指针元素的数组,为什么是66个呢?不是32就可以了么?这里Doug Lea使用了一个技巧,如果按照我们的常规想法,也许会申请32malloc_chunk结构体指针元素的数组,然后再给链表申请一个头节点(即32个),再让每个指针元素正确指向而形成32个具有头节点的链表。事实上,对于malloc_chunk类型的链表“头节点”,其内的prev_foothead字段是没有任何实际作用的,因此这两个字节如果不合理使用的话那就是白白的浪费。我们再来看一看66malloc_chunk结构体指针元素的数组占了多少内存空间呢?结果为66*4=264字节。而32malloc_chunk类型的链表“头节点”需要多少内存呢?32*10=320,真的是320么?不是,刚才不是说了,prev_foothead这两个字段是没有任何实际作用的,因此完全可以被重用(覆盖),因此实际需要内存为32*8=256264大于256,那么这66malloc_chunk结构体指针元素数组所占内存空间就可以存储这32个头节点了,事实上Doug Lea也是这么做的。我们来看下于此相关的这一句代码:

#define smallbin_at(M, i)   ((sbinptr)((char*)&((M)->smallbins[(i)<<1])))

其中的sbinptr也是malloc_chunk结构体指针类型typedef struct malloc_chunk* sbinptr;),M表示前面提到的结构体malloc_state,各位仔细体会一下这句代码中的强制转换就会理解这种技巧了。下面给个更直观的图便于理解:

最后,至于为什么是66个数组元素而不是6465,这个仔细想想也好理解,好了,就到这,下篇继续吧。

 

转载请保留本博客地址连接[http://lenky0401.cublog.cn],谢谢。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值