zoukankan      html  css  js  c++  java
  • 空间配置器

    一、SGI标准的空间配置器,std::allocator

    SGI定义了一个符合部分标准,名为allocator的配置器,但由于效率不佳,其内实现仅为将new和delete做了一层简单封装,故没有被建议使用。

    二、SGI特殊的空间配置器,std::alloc

    双层级配置器,第一级配置器直接使用malloc和free,第二级配置器则根据情况采用不同的策略,具体策略为:当配置区块超过128bytes,视为大区块,直接调用第一级配置器;当配置区块小于128bytes,视为小区块,采用内存池管理方式。在SGI STL中同时采用了第一级和第二级两种配置器的方式。

    一个重要的流程图如上。根据是否定义__USE_MALLOC,来确定是否只采用第一级配置器,或是第一第二级配置器并存。其中simple_alloc作为了一个类接口,封装了空间配置器的内存申请和释放。

    三、第一级配置器,__malloc_alloc_template

    第一级配置器的实现主要是封装了malloc,free,realloc等系统函数。看一下具体实现。

    其中这里的oom_xxx是函数指针,对应了不同情况下处理内存不足。在函数中循环调用“内存不足处理例程”,这里的“处理例程”自行设定,如果没有实现,oom_xxx将抛出bad_alloc异常信息,或者直接exit(1)终止程序。

    四、第二级配置器,__default_alloc_template

    第二级配置器采用了一些策略,用于避免太多太小额区块造成的内存碎片。具体策略为:如果区块超过128bytes,则交给第一级配置器处理,如果小于128bytes,则以内存池管理(每次配置一块内存,都维护对应的自由链表free-list,下次如果有相同大小的内存需求,直接从free-list抽出,如果释放了区块,则由配置器回收free-list)

    1、空间配置函数allocate()实现

     

    上述如果大于了128就直接调用第一级配置器,否则申请内存池分配,具体的示意图如下:

    1)首先根据需要申请的大小n,找到对应的free_list中的位置,FREELIST_INDEX实现了内存对齐。

    2)将当前区块指针赋值result

    3)将当前free_list已分配区块抽出,并返回客端result

    2、空间释放函数deallocate()实现

    代码略(详见《STL源码剖析》),具体流程为:

    1)大于128则直接调用第一级配置器的释放函数

    2)根据释放的内存大小n,找到对应的free_list

    3)回收区块,调整free_list

    示意图如下:

    3、重新填充free lists

    如果free_list中没有可用区块时,则调用refill(),为free list重新填充空间,新的空间将取自内存池(由chunk_alloc完成),默认情况下取得20个新节点(新区块)。具体流程为:

    1)char *chunk = chunk_alloc(n, nobjs),调用分配函数,nobjs为20,以引用方式传递;

    2)调用free list,放入新节点

    4、chunk_alloc内存池分配

    具体流程为:

    1)计算内存池剩余内存空间

    2)如果内存池剩余空间完全满足需求量,则修改内存池剩余空间,并返回所需分配的内存;

    3)如果内存池剩余空间不能完全满足需求量,但足够供应一个以上的区块,则计算能够分配的区块,修改内存池剩余空间,并返回所需分配的内存;

    4)如果内存池剩余空间连一个区块都不能提供。调用malloc分配新的内存来补充内存池,如果操作系统都没有,无法malloc新内存,则调用第一级配置器释放内存并再次尝试分配

    5)上述都无法成功分配,发出bad_alloc异常

    流程图如下:

  • 相关阅读:
    各职业岗位说明
    感慨集中所
    批量插入测试数据
    写作技巧
    Cordova学习
    CocoStudio
    maven使用感受
    org.json
    ApplicationContext
    2017
  • 原文地址:https://www.cnblogs.com/scu-cjx/p/9006962.html
Copyright © 2011-2022 走看看