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

    xiaoxiao2022-06-29  48

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

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

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

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

    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

    转载请注明原文地址: https://ju.6miu.com/read-1125512.html

    最新回复(0)