SGI STL V3.3- 空间配置器

141 阅读2分钟

构造/析构和空间配置

stl中,采用利用placement new 和主动调用析构函数的方式,将构造/析构函数与实际的内存管理解耦

template <class _T1, class _T2>
inline void _Construct(_T1* __p, const _T2& __value) {
  new ((void*) __p) _T1(__value);
}

template <class _T1>
inline void _Construct(_T1* __p) {
  new ((void*) __p) _T1();
}

template <class _Tp>
inline void _Destroy(_Tp* __pointer) {
  __pointer->~_Tp();
}

一级空间配置器

1、malloc/free
2、实现out-of-memory handler机制

二级空间配置器

目标

避免过多小尺度内存块造成内存碎片,小尺度内存碎片会造成无法回收AND为了管理内存的额外开销占比较大
避免频繁系统调用

总体解决方案

大尺度内存块(>128kb)利用一起空间配置器管理,小尺度内存块利用 freelist + memory pool管理

详细解决方案

FreeList是一个数组,用于维护不同尺度的空闲内存快
长度为128/8,每个元素指向一个链表,链表内每个元素大小为 8*(i + 1)(i为数组下标)

当FreeList中有对应尺度有空闲块时

image.png

当FreeList中无对应尺度有空闲块时

为了避免频系统调用,向内存池申请一大块内存(最多20*n),填充对应尺度的FreeList image.png

内存池内存分配逻辑

内存池不释放内存,只为freelist分配内存

  • 内存池剩余空间足够直接分配n * nobj
  • 内存池剩余空间不太够,能分配几个n分配几个
  • 内存池剩余空间完全不够,一个n也不够
    • 将内存池目前有的内存分配给对应较小尺度的freelist元素
    • 向系统申请2 * n * nobj内存,一半给freeList,一半内存池留着
    • 若申请失败
      • 向较大尺度freelist元素腾挪空闲空间
      • 较大尺度freelist元素也没有空闲空间,调用一级空间配置器,尝试借助out-of-memory机制获取内存