STL 實現簡單的空間配置器

2021-08-05 21:38:08 字數 4551 閱讀 2028

實現方式:

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...