實現方式:
stl原始碼中的空間配置器的實現分為一級與二級空間配置器;
所謂的一級空間配置器:(實現特點)
直接使用malloc函式申請記憶體
自定義清除函式;(當malloc失敗之後,呼叫清除函式來釋放一部分的記憶體空間,以便malloc的成功)
假設呼叫清除函式之後,還是malloc失敗的話,就需要丟擲異常 (bad_alloc)
**實現:
//實現一級空間配置器
templateclass __malloc_alloc_template
return result;
} //空間釋放
static void deallocate(void * del)
//設定自定義的清理函式 函式返回的是原來的清理函式
//函式原型的意思就是
//定義乙個函式 返回值是 靜態的函式指標引數為空
//這個函式的引數為 函式指標引數 為 空 func
static void (*set_malloc_handler(void (* func)()))()
private:
static void (*___malloc_alloc_oom_handler)();
//表示當前malloc失敗記憶體不足,呼叫自定義的清理函式
static void * omm_malloc(size_t n)
//呼叫清理函式
my_malloc_handler();
//呼叫完之後重新malloc來申請空間
result = malloc(n);
if(result)
}}};
templatevoid (*__malloc_alloc_template::___malloc_alloc_oom_handler)()=null;
實現方式:
在這裡引入記憶體池與自由鍊錶來實現二級空間配置
二級空間配置器的優缺點:
我們都知道,編譯器在使用者態與核心態之間的轉換是十分的耗時的。
所以,我們可以事先申請一大片的記憶體空間;將它儲存起來,等到需要動態開闢空間的時候,直接到這塊空間上切一塊,
直到用完之後,重新申請;
何為自由鍊錶?
就是使用鍊錶將所需要大小的記憶體塊鏈到一塊。
sgi二級空間配置器儲存的自由鍊錶的空間塊大小都是8的倍數;並且會將任何小區域的記憶體塊的大小調至8 的倍數(
各自管理大小分別為 8, 16, 24, 32, 40, 48, 56, 64, 72,80, 88, 96, 104, 112, 120, 128 bytes,
當需要的空間大小超過128byte時,直接呼叫一級空間配置器。
實現**:
//實現二級空間配置器
templateclass __default_alloc_template
//小於128的直接到自由鍊錶中獲取
//index:得到大小為n的空間要在自由鍊錶的下標為index處獲得
size_t index = freelist_index(n);
//result表示的就是自由鍊錶的第一結點;
obj* result = free_list[index];
if(result== null)
//表示的當前的自由鍊錶中有此大小的記憶體塊;直接拿到;
//更新當前的自由鍊錶
free_list[index] = result->free_list_link;
return result;
} //refill函式表示的是要是當前的自由鍊錶中沒有此大小的記憶體塊
//需要來從記憶體池中來切分
static void * refill(size_t n)
//其他就表示的是得到的記憶體塊的個數大於1
//需要將剩餘的記憶體塊掛接到的自由鍊錶中
size_t index = freelist_index(n);
//cur表示的就去除第乙個要返回的記憶體塊,的第二個記憶體塊
obj * cur = (obj*)chunk + n;
free_list[index] = cur;
for(size_t i = 2;i < nobjs;++i)
cur->free_list_link = null;
return (void *)chunk;
} //chunk_alloc函式來從記憶體池中切分大小為size的記憶體塊 需要的個數為nobjs
//nobjs傳引用 ,返回的是實際切分的記憶體塊個數
static char * chunk_alloc(size_t size,size_t & nobjs)
else if(bytes_left >=size)
else
//重新開闢新空間
size_t bytes_to_get = 2 * total_bytes + round_up(heap_size>>4);//bytes_to_get表示新開闢空間的大小
start_free = (char*)malloc(bytes_to_get);
if(start_free == null)
}end_free = 0 ;
start_free = (char*)__malloc_alloc_template<0>::allocate(bytes_to_get);
}heap_size = heap_size+ bytes_to_get;
end_free = start_free + bytes_to_get;
return chunk_alloc(size,nobjs);
} }static void deallocate(void * p,size_t n)
//將釋放的空間連到自由鍊錶上
size_t index = freelist_index(n);
del->free_list_link = free_list[index];
free_list[index] = del;
}private:
//表示的小型的區域的上調邊界
enum ;
//自由鍊錶的鏈結的記憶體的最大值
enum ;
//表示的是自由鍊錶的個數
enum ;
//round_up函式將bytes上調到 8 的倍數
static size_t round_up(size_t bytes)
//根據要開闢的空間大小來得到 該大小在自由鍊錶中的下標
static size_t freelist_index(size_t bytes)
private:
//鍊錶的結點
union obj
; //自由鍊錶陣列 ,內部儲存乙個個的記憶體塊鍊錶
static obj * free_list[__nfreelists];
static char* start_free;//記憶體池的起點
static char* end_free;//記憶體池的結尾
static size_t heap_size ;//記憶體池的大小; };
實現:
#ifdef __use_malloc
typedef __malloc_alloc_template<0> alloc;
#else
typedef __default_alloc_templatealloc;
#endif //__use_malloc
templateclass ******_alloc
//表示申請乙個t型別的空間
static t * allocate(void)
static void deallocate(t * del)
static void deallocate(t * del,size_t n) };
#includevoid test()
STL 空間配置器
stl有6大元件 容器 演算法 迭代器 仿函式 配接器 分配器。它們之間的密切關係是stl的精髓所在,容器用來存放資料,而容器存在的前提是要有分配器給它分配記憶體,接下來需要實現演算法,迭代器便作為演算法來對容器資料操作的橋梁,演算法可以使用仿函式完成不同的策略變化,配接器可修飾或套接仿函式。說了麼...
STL 空間配置器
stl空間配置器的底層原理 維護了乙個狹義的記憶體池,並且用乙個自由鍊錶來維護該記憶體池。該自由鍊錶比較類似於雜湊的開鏈法的儲存結構。源 pragma once using namespace std define throw bad alloc cerr out of memory endl ex...
STL空間配置器
一級空間配置器 ifndef malloc alloc template h define malloc alloc template h if 0 include define throw bad alloc throw bad alloc elif defined throw bad alloc...