前言
第一级是直接调用malloc
分配空间, 调用free
释放空间, 第二级三就是建立一个内存池, 小于128字节的申请都直接在内存池申请, 不直接调用malloc
和free
. 本节分析第二级空间配置器, STL将第二级配置器设置为默认的配置器, 所以只要一次申请的空间不超过128字节就默认在内存池中申请空间, 超过才会调用第一级配置器.
第二级配置器
首先先来介绍3个常量.
__ALIGN
: 以8字节进行对齐__MAX_BYTES
: 二级分配器最大分配的内存大小__NFREELISTS
: 128字节能分配的的链表个数, 并且从每个链表保存的内存大小都是8的倍数, 而且都比前一个大8字节, 也就是分别是8, 16, 32…128字节
// 二级配置器
enum {
__ALIGN = 8}; // 设置对齐要求. 对齐为8字节, 没有8字节自动补齐
enum {
__MAX_BYTES = 128}; // 第二级配置器的最大一次性申请大小, 大于128就直接调用第一级配置器
enum {
__NFREELISTS = __MAX_BYTES/__ALIGN}; // 链表个数, 分别代表8, 16, 32....字节的链表
再介绍一个宏操作, 这是进行对齐操作, 将不满8的倍数的填充成8的倍数.
static size_t FREELIST_INDEX(size_t bytes) \
{
\
return (((bytes) + ALIGN-1) / __ALIGN - 1);\
}
从allocate先切入分析
- 先判断申请的字节大小是不是大于128字节, 是, 则交给第一级配置器来处理. 否, 继续往下执行
- 找到分配的地址对齐后分配的是第几个大小的链表.
- 获得该链表指向的首地址, 如果链表没有多余的内存, 就先填充链表.
- 返回链表的首地址, 和一块能容纳一个对象的内存, 并更新链表的首地址
static void * allocate(size_t n)
{
obj * __VOLATILE * my_free_list;
obj * __RESTRICT result;
if (n > (size_t) __MAX_BYTES)
{
r