#### STL内存分配
由于小型的内存区块会因此内存分配碎片,SGI STL设计中使用了**双层级配置器**,**第一级配置器直接使用malloc()和free()**,申请内存大于128字节时调用;第二级配置器采用**内存池**的方式来管理。
STL内存分配器在文件`<stl_alloc.h>`中实现,**__malloc_alloc_template**和**__default_alloc_template**,分配器都需要实现两个接口allocate和deallocate。本文主要讨论第二级的分配器的实现。
**__default_alloc_template**:STL默认小内存分配器
#####分配器的实现
维护了16个free list,每个list上集合着大小分别为8,16,24,...128大小的内存块。如果请求的内存块大小大于128bytes,就转调用第一级配置器。使用了链表结构管理内存块:
```cpp
union obj{
union obj* free_list_link; //当作为自由链表的一个结点时,存储其下一个节点的地址
char client_date[1]; //当其作为返回值时,返回的正好是分配内存的首地址
}
```
相当于每个块前面4个字节用来存储节点头结构,结构体中client_data返回的实际上可用的内存块地址。free_list中找到合适的块后,会将下一个空闲块的地址写在原来这个free_list数组元素的位置。一般而言内存块是连续的。

内存申请流程:
1. 大于128字节,使用第一级配置器向系统申请,malloc不成功会调用**set_new_handler**来处理异常。
2. 小于128字节,使用第二级适配器。如果有对应大小的free_list内存块,正常返回;如果free_list没有:
- 2.1 向内存池要20个块大小的内存,内存池尽量满足;如果内存池也没有足够的内存:
- 2.2 调用malloc从系统heap中申请内存,申请大小 **bytes_to_get=2*total_bytes+ROUND_UP(heap_size>>4)**,如果申请成功了并且内存池中有剩余内存,会将内存池的剩余内存非配给free_list。
3. 如果2.2失败,会求助于第一级配置器,主要是想借助于第一级配置器里的异常处理,例如**out_of_memory**中申请到一点内存。如果这一步也失败,那么就是彻底失败了。
##### 释放器
STL中调用deallocate后,对于小块内存,会放入到free_list中而不是释放回系统。
由于小型的内存区块会因此内存分配碎片,SGI STL设计中使用了**双层级配置器**,**第一级配置器直接使用malloc()和free()**,申请内存大于128字节时调用;第二级配置器采用**内存池**的方式来管理。
STL内存分配器在文件`<stl_alloc.h>`中实现,**__malloc_alloc_template**和**__default_alloc_template**,分配器都需要实现两个接口allocate和deallocate。本文主要讨论第二级的分配器的实现。
**__default_alloc_template**:STL默认小内存分配器
#####分配器的实现
维护了16个free list,每个list上集合着大小分别为8,16,24,...128大小的内存块。如果请求的内存块大小大于128bytes,就转调用第一级配置器。使用了链表结构管理内存块:
```cpp
union obj{
union obj* free_list_link; //当作为自由链表的一个结点时,存储其下一个节点的地址
char client_date[1]; //当其作为返回值时,返回的正好是分配内存的首地址
}
```
相当于每个块前面4个字节用来存储节点头结构,结构体中client_data返回的实际上可用的内存块地址。free_list中找到合适的块后,会将下一个空闲块的地址写在原来这个free_list数组元素的位置。一般而言内存块是连续的。

内存申请流程:
1. 大于128字节,使用第一级配置器向系统申请,malloc不成功会调用**set_new_handler**来处理异常。
2. 小于128字节,使用第二级适配器。如果有对应大小的free_list内存块,正常返回;如果free_list没有:
- 2.1 向内存池要20个块大小的内存,内存池尽量满足;如果内存池也没有足够的内存:
- 2.2 调用malloc从系统heap中申请内存,申请大小 **bytes_to_get=2*total_bytes+ROUND_UP(heap_size>>4)**,如果申请成功了并且内存池中有剩余内存,会将内存池的剩余内存非配给free_list。
3. 如果2.2失败,会求助于第一级配置器,主要是想借助于第一级配置器里的异常处理,例如**out_of_memory**中申请到一点内存。如果这一步也失败,那么就是彻底失败了。
##### 释放器
STL中调用deallocate后,对于小块内存,会放入到free_list中而不是释放回系统。