STL分爲6大組件,容器、算法、迭代器、適配器、仿函數、空間配置器;容器距離咱們使用者最近,可是容器之下,是空間配置器。沒有空間,不成容器。算法
STL的空間配置器分類:函數
- 一級空間配置器---__malloc_alloc_template
- 二級空間配置器--__default_alloc_template

上圖是SGI STL空間配置器的結構,用戶調用配置器中的allocate(size_t n)申請內存並返回空間指針,調用deallocate(void *p, size_t n)釋放p指向的內存。區塊鏈
一級配置器中的allocate(size_t n):指針
- __malloc_alloc_template中的allocate()直接調用malloc(),若是內存不足則再調用oom_malloc(),不然直接返回
- oom_malloc()中不斷嘗試調用malloc(),而且調用用戶設置的處理例程(void (*oom_handler)()),若是用戶沒有設置處理例程,則跑出異常且exit(0),不然返回得到的空間指針
二級配置器中的allocate(size_t n):調試
- __default_alloc_template中的allocate()判斷size是否大於128,大於則轉給一配置器中的allocate()處理,不然檢查free_list[16]中是否有有適當的區塊,存在則從free_list[16]中抽取區塊並返回區塊指針,不然調用refill()填充free_list[16]並返回獲得的第一個區塊
- refill()直接調用chunk_alloc()從內存池中申請區塊,默認申請20個區塊,實際得到的區塊以參數傳回(傳址),判斷得到的區塊是否等於1,若是等於則直接返回區塊指針,無須調整free_list[16],不然返回頭區塊指針,而且將後面的區塊連接起來(使用侵入式鏈表)並掛接到free_list[i]上
- chunk_alloc()查看內存池餘下空間是否知足20個區塊,知足則返回20個區塊,不知足則再檢查是否知足1個區塊以上,知足則返回x個區塊,並修改nobjs的值以傳出實際返回的區塊個數,不然將剩餘的區塊放入合適的free_list[i]中,再度調用malloc()。成功則返回,失敗則檢查free_list[16]中是否存在還沒有使用的足夠區塊,存在則回收到內存池中再遞歸調chunk_alloc(),不然轉到一級空間配置器。(PS:返回區塊以後須要調整內存池中的頭指針---start_free;區塊插入到free_list中時用的是頭插法)
如下下是free_list[16]的示意圖:code

STL中對於free_list使用了遞歸
union obj{
obj *next;
char client_data[1];
}
來連接區塊,由於區塊掛接在free_list上時是不存儲內容的,因此能夠用侵入式鏈表來連接。此obj直接位於區塊的前四字節,存儲下一個區塊的地址(即next),通過調試,知道client_data此時只是下個區塊地址的第一個字節,我暫且認爲它在調試的時候起到一個輔助做用(沒有找到太可靠的資料來講明client_data[1])。內存