C++之STL空间置配器

空间配置器(SGI版)

STL里面的空间配置主要分为两级,一级空间配置器(__malloc_alloc_template)和二级空间配置器(__default_alloc_template)。在STL中默认如果要分配的内存大于128个字节的话就是大块内存,调用一级空间配置器直接向系统申请,如果小于等于128个字节的话则认为是小内存,则就去内存池中申请。一级空间配置器很简单,直接封装了malloc和free处理,增加_malloc_alloc_oom_handle处理机制。二级空间配置器才是STL的精华,二级空间配置器主要由memoryPool+freelist构成。
二级空间配置器:
二级空间配置器使用内存池+自由链表的形式避免了小块内存带来的碎片化,提高了分配的效率,提高了利用率。SGI的做法是先判断要开辟的大小是不是大于128,如果大于128则就认为是一块大块内存,调用一级空间配置器直接分配。否则的话就通过内存池来分配,假设要分配8个字节大小的空间,那么他就会去内存池中分配多个8个字节大小的内存块,将多余的挂在自由链表上,下一次再需要8个字节时就去自由链表上取就可以了,如果回收这8个字节的话,直接将它挂在自由链表上就可以了。
为了便于管理,二级空间配置器在分配的时候都是以8的倍数对齐。也就是说二级配置器会将任何小块内存的需求上调到8的倍数处(例如:要7个字节,会给你分配8个字节。要9个字节,会给你16个字节),尽管这样做有内碎片的问题,但是对于我们管理来说却简单了不少。因为这样的话只要维护16个free_list就可以了,free_list这16个结点分别管理大小为8,16,24,32,40,48,56,64,72,80,88,86,96,104,112,120,128字节大小的内存块就行了。

二级空间配置器的逻辑步骤:

假如现在申请n个字节:
1、判断n是否大于128,如果大于128则直接调用一级空间配置器。如果不大于,则将n上调至8的倍数处,然后再去自由链表中相应的结点下面找,如果该结点下面挂有未使用的内存,则摘下来直接返回这块空间的地址。否则的话我们就要调用refill(size_t n)函数去内存池中申请。
2、向内存池申请的时候可以多申请几个,STL默认一次申请nobjs=20个,将多余的挂在自由链表上,这样能够提高效率。
进入refill函数后,先调chunk_alloc(size_t n,size_t& nobjs)函数去内存池中申请,如果申请成功的话,再回到refill函数。
这时候就有两种情况,如果nobjs=1的话则表示内存池只够分配一个,这时候只需要返回这个地址就可以了。否则就表示nobjs大于1,则将多余的内存块挂到自由链表上。
如果chunk_alloc失败的话,在他内部有处理机制。
3、进入chunk_alloc(size_t n,size_t& nobjs )向内存池申请空间的话有三种情况:
3.1、内存池剩余的空间足够nobjsn这么大的空间,则直接分配好返回就可以了。
3.2、内存池剩余的空间leftAlloc的范围是n<=leftAlloc<nobjs
n,则这时候就分配nobjs=(leftAlloc)/n这么多个的空间返回。
3.3、内存池中剩余的空间连一个n都不够了,这时候就要向heap申请内存,不过在申请之前先要将内存池中剩余的内存挂到自由链表上,之后再向heap申请。
3.3.1、如果申请成功的话,则就再调一次chunk_alloc重新分配。
3.3.2、如果不成功的话,这时候再去自由链表中看看有没有比n大的空间,如果有就将这块空间还给内存池,然后再调一次chunk_alloc重新分配。
3.3.3、如果没有的话,则就调用一级空间配置器分配,看看内存不足处理机制能否处理。

空间配置器的其他问题

1、在空间配置器中所有的函数和变量都是静态的,所以他们在程序结束的时候才会被释放发。二级空间配置器中没有将申请的内存还给操作系统,只是将他们挂在自由链表上。所以说只有当你的程序结束了之后才会将开辟的内存还给操作系统。
2、由于它没有将内存还给操作系统,所以就会出现二种极端的情况。
2.1、假如我不断的开辟小块内存,最后将整个heap上的内存都挂在了自由链表上,但是都没有用这些空间,再想要开辟一个大块内存的话会开辟失败
2.2、再比如我不断的开辟char,最后将整个heap内存全挂在了自由链表的第一个结点的后面,这时候我再想开辟一个16个字节的内存,也会失败。
或许我比较杞人忧天吧,总的来说上面的情况只是小概率情况。如果非得想办法解决的话,我想的是:针对2.1我们可以引入释放二级空间配置器的方法,但是这个释放比较麻烦。针对2.2我们可以合并自由链表上的连续的小的内存块。
3、二级空间配置器会造成内碎片问题,极端的情况下一直申请char,则就会浪费7/8的空间。但是整体来说,空间配置器的性能还是蛮高的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值