其實題目有些譁衆取寵,主要想表達的是對chunk_alloc函數中兩個地方存在疑問,想問問諸位怎麼理解這兩處的。數組
下面先給出chunk_alloc代碼實現,同時大概說明一下函數的功能以及每一處代碼的做用。函數
SGI的內存配置器分紅兩層:第一層直接調用malloc,第二層是本身作了一個內存池來分配。下面說下第二層配置器的思路:指針
第二層配置器首先設置了一個free_list[16]的數組,數組中是指針,分別指向一塊內存,指針類型定義以下:blog
union obj {遞歸
union obj *free_list_link;內存
char client_data[1];rem
};get
總之,free_list每一個下標連接的內存大小爲:8B、16B、24B、32B、40B、...、128B。共16個。requests
如今假如要分配一塊32B的內存,但free_list[3]所指向的指針爲NULL,即空閒鏈表free_list中沒有32B的內存,這時候就須要經過下面的_S_chunk_alloc來分配內存給free_list了。默認每次分配是分配20個大小爲32B的內存。it
即_S_chunk_alloc第二個參數傳入值爲20,但系統不必定能分配20個,因此用的是引用。_S_chunk_malloc主要分三種狀況來處理:
一、現有內存池容量知足你的需求:32B * 20個,直接返回給你這麼大一塊內存;
二、現有內存池容量不能知足這麼多個,即20個,但能夠知足1個,那先給你free_list對應項分配一個32B再說;
三、現有內存池容量連一個都知足不了,那隻能利用malloc從堆中分配內存。
從堆中分配內存時,首先把當前內存池中剩餘的一些零碎內存賦給free_list中;
而後從堆中malloc內存,修改內存池的_S_start_free、_S_end_free指針。(這兩個指針分別指向內存池的起始地址和結束地址)。
再而後遞歸調用_S_chunk_malloc函數。
個人問題是:一、重置零碎內存時是否有問題,以下代碼中所示。
二、malloc新的內存以後,修改_S_end_free的代碼是否正確。
所有代碼以下,個人疑問解釋說明再下面,你們先看下代碼理解一下這個函數,而後看下個人思路哪裏出錯了,謝謝!
template <bool __threads, int __inst> char* __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, int& __nobjs) { char* __result; size_t __total_bytes = __size * __nobjs; size_t __bytes_left = _S_end_free - _S_start_free; // 內存池剩餘空間 if (__bytes_left >= __total_bytes) { // 內存池剩餘空間徹底知足需求 __result = _S_start_free; _S_start_free += __total_bytes; return(__result); } else if (__bytes_left >= __size) { // 內存池剩餘空間不能徹底知足需求,但足夠供應一個(含)以上的區塊 __nobjs = (int)(__bytes_left/__size); __total_bytes = __size * __nobjs; __result = _S_start_free; _S_start_free += __total_bytes; return(__result); } else { // 內存池剩餘空間連一個區塊的大小都沒法提供 size_t __bytes_to_get = 2 * __total_bytes + _S_round_up(_S_heap_size >> 4); // Try to make use of the left-over piece. // 把內存池當前剩下的一些小殘餘零頭利用一下。 if (__bytes_left > 0) { _Obj* __STL_VOLATILE* __my_free_list = _S_free_list + _S_freelist_index(__bytes_left); // 這裏對嗎?假如__bytes_left = 15,則_S_freelist_index(15) = 1, // 即16B的位置,而實際上只剩下了15B? ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list; *__my_free_list = (_Obj*)_S_start_free; } _S_start_free = (char*)malloc(__bytes_to_get); if (0 == _S_start_free) { size_t __i; _Obj* __STL_VOLATILE* __my_free_list; _Obj* __p; // Try to make do with what we have. That can't // hurt. We do not try smaller requests, since that tends // to result in disaster on multi-process machines. for (__i = __size; __i <= (size_t) _MAX_BYTES; __i += (size_t) _ALIGN) { __my_free_list = _S_free_list + _S_freelist_index(__i); __p = *__my_free_list; if (0 != __p) { *__my_free_list = __p -> _M_free_list_link; _S_start_free = (char*)__p; _S_end_free = _S_start_free + __i; // 這裏肯定每一塊內存大小都是__i嗎? return(_S_chunk_alloc(__size, __nobjs)); // Any leftover piece will eventually make it to the // right free list. } } _S_end_free = 0; // In case of exception. _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get); // This should either throw an // exception or remedy the situation. Thus we assume it // succeeded. } _S_heap_size += __bytes_to_get; _S_end_free = _S_start_free + __bytes_to_get; return(_S_chunk_alloc(__size, __nobjs)); } }
個人問題解釋:
一、假如__bytes_left = 15B,那麼_S_freelist_index(__bytes_left) = 1,便是說應該把15B放到free_list中16B的這一項裏面,這不錯了嗎?
二、_S_end_free = _S_start_free + __i;怎麼就能夠肯定free_list中對應__i這一項的大小都是__i,難道不會出現容量>__i,但小於__i + 8的嗎?這樣_S_end_free不就出錯了嗎?