本文主要讲讲 GNU-C++ 4.9 下的扩展内存分配器
首先 GNU-C++ 4.9 有 7 个扩展的内存分配器
- new_allocator
- malloc_allocator
- pool_allocator
- __mt_alloc
- array_allocator
- debug_allocator
- bitmap_allocator
主要看看 pool_allocator
array_allocator
bitmap_allocator
以下源码都可在 .../ext/*.h
下找到 我将其进行了适当的 删减和修改
__gnu_cxx::new_allocator
直接用 ::operator new
和 ::operator delete
实现出来的 好处是 可以被重载 没啥特色
1 | template<typename _Tp> |
__gnu_cxx::malloc_allocator
直接用 std::malloc
和 std::free
实现的 好处是 少调用 一次 operator new
和 operator delete
函数 节省一次入栈出栈开销 也没啥特色
1 | template<typename _Tp> |
__gnu_cxx::pool_allocator
G2.9 容器默认配置器 在 我的 C++ 内存管理 之 STL内存分配实现原理 这篇文章中 的 GNU-C++ 2.9 std::alloc 原理
已经分析过了
__gnu_cxx::__mt_alloc
适用于多线程的内存分配
__gnu_cxx::array_allocator
用于分配固定大小的内存块 使用 标准库 中的 std::array
实现 无需再去调用 ::operator new
和 ::operator delete
在进入 main 之前就可以用了 因为是用的 静态数组
1 | // tr1 是因为 在 C++ 11之前 array不属于标准库的内容 属于一个小版本 |
要注意的是 array 因为是静态的 所以不需要 释放 因此 你调用 deallocate
是没有任何操作的
不过 如果说 deallocate
能够回收掉已经分出去的数组中的某块的话 那可能利用率更高一些
1 | // 静态数组 |
__gnu_cxx::debug_allocator
不做分配归还动作 里面传入一个真正的 allocator
来分配归还内存 正如其名 不做事情 只是用来 debug 用的 每次申请 多申请一块 来记录 分配的内存 然后归还的时候 assert
来查看 分配的 size
是否正确
有点类似 malloc
中的 cookie
1 | template<typename _Alloc> |
__gnu_cxx::bitmap_allocator
使用 bitmap
来查找 被使用和未被使用的内存块
内部实现了一个 mini vector
和 普通的 vector
一样 会 两倍
成长
一整块称之为 Super Block 每一个 Block 相当于一个元素单位
1 | Super Blocks Size 记录已使用的块数 位图数组 记录某块是否被使用 64个Blocks 被 mini vector 所管理 |
假设 此时在32位系统下 一个内存块为 8 字节 则 Super Blocks Size 为 = 4 + (4 * 2) + 8 * (64 * 8) = 524字节
如果 全回收了 就 按照 Super Block 的大小 顺序放到 free_list
中 其实也是一个 vector 并且下次分配规模减半 (因为vector 每次分配都是两倍递增) 当 free_list
超过64个 Super Block 时 如果最后进来的 比最后面的还要大 就将其还给 OS (总而言之就是把最大的还给 OS)
如果 前面一个 Super Block 本来没区块 现在回收到了区块 此时又请求了区块的话 会从后面一个 Super Block 去分配 但是如果 后面一个 Super Block 不存在的话 则从 前面一个 Super Block 取
free_list
存在的意义就是 先把 Super Block 存起来 万一以后有用 就不用重新创建了
1 | template<typename _Tp> |