《STL 源码剖析》 内存配置器 笔记

例子:

class Foo{...};

Foo*pf=new Foo;//配置内存,然后构造对象

delete pf;     //析构对象,然后释放内存

new算式:        

配置内存:调用::operator new;

调用Foo::Foo()构造对象内容

delete算式:

调用Foo::~Foo()析构对象

调用::operator delete释放内存

STL allocator将这2个阶段的工作分开:

1-内存配置---alloc::allocate()

  内存释放---alloc::deallocate()

2-对象构造---::construct()

  对象析构---::destroy()

      《STL 源码剖析》 内存配置器 笔记_第1张图片

   

第一级配置器

class _malloc_alloc_template

{

处理内存不足:

*oom_malloc();不断尝试释放,配置,再释放,再配置(中间调用malloc)

*oom_realloc();不断尝试释放,配置,再释放,再配置(中间调用realloc)

allocte():调用malloc(第一级配置器)

deallocate():调用free(第一级配置器)

reallocte():调用reallocate(第一级配置器)

set_malloc_hander():模仿C++set_new_hander(),溢出控制器

}

注意:第一级配置器调用的流程图

       《STL 源码剖析》 内存配置器 笔记_第2张图片

  

第二级配置器剖析

作用:避免小区块造成内存碎片,流程图:

     《STL 源码剖析》 内存配置器 笔记_第3张图片

   

自由链表的实现技巧

第二级配置器:

1-      自动将任何小区块的内存需求量上调至8的倍数(例如客端要求30B,调整为32B);

维护16个自由链表(各自管理大小为8,16,24,…,128B)

      《STL 源码剖析》 内存配置器 笔记_第4张图片

     

class _default_alloc_template

{

ROUND_OP(bytes){return(bytes+7)&~7;}bytes上调至8的倍数

free_lists[16];

根据区块大小,决定第n号free_lists

FREELIST_INDEX(bytes){return(bytes+7)/8-1;}

refill(n);

chunk_alloc(size,&nobjs);配置一大块空间,可容纳nobjs个大小为size的区块;

                         如果不便,nobjs可能会降低

*start_free:内存池的起始位置

*end_free;内存池的结束位置

heap_size

allocate();

deallocate();

reallocate();

}

allocate实现分配区块

    《STL 源码剖析》 内存配置器 笔记_第5张图片

   《STL 源码剖析》 内存配置器 笔记_第6张图片 

deallocate()回收区块

      《STL 源码剖析》 内存配置器 笔记_第7张图片

  

chunk_alloc() 详见代码

      《STL 源码剖析》 内存配置器 笔记_第8张图片
  注意:
1-如果内存池连一个区块空间都无法供应,则需要利用malloc()从heap中配置内存,
 为内存池注入活水,新水量的大小为需求量的两倍,加上一个随配置次数增加的附加量。
2-如果整个heap空间都不够了,malloc()失败,chunk_alloc()就寻找区块够大,未用的自由链表;
找到则交出一块,否则调用第一级配置器(其实第一级配置器也是调用malloc()配置内存,但它有out of memory处理机制,可以抛出异常。)
  例子:
        
    《STL 源码剖析》 内存配置器 笔记_第9张图片
     《STL 源码剖析》 内存配置器 笔记_第10张图片
    



你可能感兴趣的:(《STL 源码剖析》 内存配置器 笔记)