stl源码剖析(一)空间配置器

STL空间配置器:

1.空间配置器为什么不叫内存配置器:

配置的空间可以是内存也可以是硬盘,但是SGI STL的空间配置器是内存


2.1标准空间配置器:std::allocator 

配置器是默认选项:vector的声明如下:template Alloc=alloc> 

class vctor{...}

比如在vs2010中定义一个vector对象:vector > ivec,一般来讲std::allocator是默认缺省的,即vector ivec

标准配置器很少使用,因为效率低,只是用allocate和deallocate对::operator new和::operator delete进行了一层简单封装,

返回分配空间指向的指针

2.2特殊空间配置器:std::alloc

效率高,原因是将上面new中步骤分解为两步:1.内存配置,alloc::allocate()  2.对象构造,::construt(),

(delete同理,先::destroy(),后alloc::deallocate)

内存配置在,而构造析构专门由负责


2.3 std::alloc详解:空间配置和释放

空间分配需要考虑:

1.向system heap要求空间

2.内存不足怎么办

3.过多小型区域造成的内存碎片(双层级配置器,第一级使用malloc()和free(),第二级后面解释)


tips:c++的内存配置操作是::operator new()和::operator delete(),实际上使用c的malloc()和free()完成内存配置和释放

双层级配置器策略:

1>需要的内存大于128bytes时,调用第一级配置器,直接使用malloc()和free()配置

2>需要的内存小于128B时,为了减少过多的内存碎片,使用第二级配置器,内存池方式分配


默认同时开启第一二级,且将alloc封装成simple_alloc来适应stl标准

第一级配置器:__malloc_alloc_template

第一级直接使用malloc,free,realloc配置,allocate()封装了malloc和oom_malloc,

正常调用malloc分配空间,但当内存不足时,调用oom_malloc(),oom_malloc有内循环,

不断调用内存不足处理程序(若用户没设定,直接丢bad_alloc异常,或exit(1)直接中止),直到成功分配

第二级配置器:__default_alloc_template

维护16个free-lists(8~128,都是8的倍数)(如果申请额空间不是8的倍数,自动补上)

每个结点定义如下:union obj{

union obj* free_list_link;

char client_data[1];};

为了维护链表,每个结点需要free_list_link来指向下一个结点,不是也会浪费空间么?

解决:结点定义如上,使用union,公用空间,提高效率,在非强型语言(c++)中很普遍,强型(java)不可以

class __defaulta_alloc_template{

......

static char *start_free;//内存池起始位置

static char *end_free;

static heap_size;

allocate(n);//>128,调用第一级配置器, 否则找对应的free_list,若找不到对应的free_list则重新填充free list

};

每个free_list指向一些区块,比如free_list[2]指向的区块大小为24,可以有n个

若对应的free_list没有区块可以用了,则调用refill()

refill新的空间将取自内存池(调用chunk_alloc),默认一次获得20个新区块


chunk_alloc(size ,nobjs) size为所需要的区块大小,nobjs为返回给对应free list的个数(默认为20个)

内存池通过end_free-start_free来判断内存池的水量,分3种情况:

1.若水量充足,就直接调出20个区块,第一个交给客户端,剩下的19个交个对应的free list维护

2.若可以提供一个以上,但<20个区块,就返回实际可提供的区块,nobjs更新为实际返回区块数

3.一块都提供不了,内存池耗尽,此时用malloc从system heap中配置空间,1个交给客户端,19个区块交给对应free list,剩下的交给内存池








你可能感兴趣的:(STL源码剖析)