STL源码剖析之一:空间适配器(allocator)

来源:互联网 发布:vue.js 动态添加div 编辑:程序博客网 时间:2024/03/29 04:11

空间适配器是 所有组件的核心

每个操作系统都有自己的内存分配器

他承担着内存分配 管理 释放

作为模版参数传递到每个容器去


allocate函数分配一片连续的未被构造的空间备用,

deallocate  函数释放空间

construct函数调用布局new,同时调用构造函数,对象被new定位在指定位置

destory 函数调用析构函数,

适配器分一级和二级


第一级适配器剖析:

第一级配置器以malloc() free() remalloc() 等C函数执行实际的内存配置 释放 重配置操作 并实现出类似

C++ new-handler的机制 这里并没有直接使用C++ new-handler机制 (没有使用::operator new来配置内存)

SGI第一级配置器的allocate()和remalloc()都是在调用malloc()和remalloc() 不成功之后 改调用oom_malloc() 和

oom_realloc() 后两者都有内循环,不断调用 ‘内存不足处理例程’,期望在某次调用之后获得足够的内存而圆满

完成任务。若内存不足,会抛异常,异常处理应该提前设定。

但是如果内存不足处理例程没有被设定当内存不足时直接抛出‘__THROW_BAD_ALLOC’丢出bad_alloc异常信息。


第二级适配器剖析:

SGI第二级配置器的做法是:如果区块够大,超过128bytes就移交第一级配置器处理。当区块小于128bytes

则以内存池管理:每次配置一大块内存,并维护对应的自由链表;下次若再有内存需求,直接从free list中取。

如果使用者释放了小额区域 就由配置器会收到free-list。为了方便管理,SGI第二级适配器会主动将任何小额区块内存需求上调至8的倍数。

为了维护自由链表 每一个节点都需要额外的指向下一个节点的指针,这对于频繁使用的类库来说,必须锱铢必较。

于是此处有了一个好的解决方案:union联合类型

union obj{

union obj* free_list_link;

char client_data[1];

};

当用户没有申请内存时 free_list_link有效指向下一个节点

当用户申请了内存时 client_data有效 指向内存首地址

同一时间只有一个value有效正是union的特点。

这种技巧在强类型语言JAVA中不会出现,但是在非强行语言C/C++中十分普遍

LUA源码中看到过储存变量也是使用union Lua的变量能相互转化也是基于词机制

参考:

http://blog.csdn.net/effective_coder/article/details/8991980

http://www.voidcn.com/blog/hujian_/article/p-5807328.html

1 0