c++中的new包含兩個動作:呼叫operaotr new分配記憶體;然後呼叫建構函式構建物件。delete也包含兩個過程:呼叫析構函式;然後呼叫operator delete釋放記憶體。
在stl中allocator將這兩個動作分開。分配記憶體由alloc:allocate()負責,釋放記憶體由alloc:deallocate()負責,建立物件由::construct()負責,析構物件由::destroy()負責。
construct(t1*p,const t2&value)
inline voide destroy(t*pointer)
inline void destroy(forwarditerator first,forwarditeratot last())
第一級配置器直接使用malloc()和free(),第二級配置器則視情況採用不同的策略:當配置區域超過128bytes,視之為足夠大,呼叫第一級配置器;當配置區域小於128bytes,視之為過小,則採用複雜的記憶體池模式,究竟是採用哪種,取決於__use_malloc().//??
sgi二級空間配置器的做法:如果塊足夠大,超過128bytes,就由一級空間配置器處理,當快小於128bytes史,以記憶體池處理。,每次配置一塊記憶體區,並維護對應自由串列,下次若再有相同大小的記憶體需求,就直接從free-list中取出。如果客戶端釋放小塊記憶體,則配置器會受到free-list中。sgi會主動將任何小塊需求上調至8的倍數,並維護16個free-list,各自管理大小分別為8,16,32,40.。。128bytes的小塊區域。
free-list的結構:
union obj
由於union的原因,從第一位來看,obj可以被視為乙個指標,指向相同形式的另乙個obj,從其第二位來看,obj可被視為乙個指標,只想記憶體區塊,一物二用。
1: 首先根據使用者需求大小,把其調節成8的倍數,然後在16個自由空閒鍊錶中去查詢
(((bytes) + __align - 1) & ~(__align-1));
2:若找到則把那塊從free_list中分配給使用者((bytes + __align -1) / __align -1);
3:若恰好找到的那一塊是null的,則呼叫refill(round_up(n))函式,refill函式的意思就是重新填充free_list鍊錶,在stl中規定的是為ree_list為null的那塊在記憶體池中選取20塊對應大小的記憶體分配給他,呼叫chunk_alloc(n,nobjs)函式,當記憶體池無法滿足分配20塊的時候則最少就要選取1塊分配給他
4:倘若此時記憶體池中剩下的記憶體大小比使用者所需記憶體型別的1塊還小的時候,則重新開闢池子(使用malloc其大小為:使用者所需大小的2倍加上池子以前總大小的十六分之一即:size_t types_to_get =2*total_types + round_up(heap_size>>4);)
6:若此時還是不可以滿足的話則呼叫一級空間配置器來分配(allocate(types_to_get)函式首先還是會直接呼叫malloc函式,然後當失敗的時候就會呼叫oo_malloc函式,oo_malloc函式首先會檢查my_malloc_handler函式指標是否是null,若null的話就直接丟擲異常,否則呼叫my_malloc_handler函式(意思是看使用者可不可以還一些記憶體給系統),然後再重新呼叫malloc函式)
《STL原始碼剖析》學習筆記 空間配置
相信大多數人應該和我一樣,對stl的認識是從使用它開始的。但是,這等利器都是雙刃劍,不明原理地使用,往往會適得其反。舉個例子來說,對vector進行增添或者刪除之後,出於記憶體安全的考慮,原有的迭代器應該摒棄不用。或許,只有真正走進stl的原始碼,才能解答這些疑問。stl原始碼剖析 這本書的原始碼來...
《STL原始碼剖析學習筆記》
1 演算法泛化過程 首先是模板 適應不同型別 其次是迭代器 具有原生指標行為的類 最後是仿函式 行為類似函式指標,但更適合泛化 泛化的優點 個人總結 1 簡化程式,提高 的可重用性 2 提高了程式的通用性 3 提高了程式的可讀性 4 提高了安全性 函式指標及仿函式 首先說說函式指標,乙個程式可能需要...
《STL原始碼剖析》學習筆記
第二章 空間配置器 allocator 考慮到小型區塊可能造成的記憶體破碎問題,sgi設計了雙層級配置器。當配置區塊超過128bytes時,便呼叫第一級配置器,即直接使用malloc free sgi的第一級配置器的allocate 和realloc 都是在呼叫malloc 和realloc 不成功...