stl記憶體池剖析空間配置器

2021-08-08 08:21:02 字數 4431 閱讀 6981

原**參考stl庫
///*具體只有記憶體分配** 類似於c++的newhander 部分**沒有列出*/

//stl空間配置器的記憶體池模型

#pragma once

#include #include #include using namespace std;

class _mallocalloctemplate//定義一級空間配置器申請大記憶體直接呼叫這個配置器;對於

;void* _mallocalloctemplate::allocate(size_t n)

return ret;

} void _mallocalloctemplate::deallocate(void *p,size_t size)

void* _mallocalloctemplate::reallocate(void *p, size_t old_size, size_t newsize)

return ret;

} enum ; //小區塊的上調邊界(8位元組對齊)

enum ; // 小區塊的最大值,上限

enum ; //free list個數為128/8=16 8位元組對齊所以需要16個指正

template//空間配置器

class __defaultalloctemplate

;//採用這樣的結構可以讓該指正的next和該指正作為乙個使用減少了變數的產生;

static char* startfree;

static char* endfree;

static size_t heapsize;

static obj* freelist[__num_free_list];

static size_t roundup(size_t bytes)//對所申請的記憶體進行8位元組對齊

static size_t freelistindex(size_t bytes)//算出大小當前的下標

static void*chunalloc(size_t size, size_t& nobjs)

else if (bytesleft >= size) // 記憶體池大小不夠分配nobjs,但是至少分配乙個

else // 記憶體池乙個都分配不了 對第一次進行記憶體池劃分對start和end進行初始haul

size_t bytestoget = 2 * totalbytes + roundup(heapsize>>4);//

startfree = (char*)malloc(bytestoget);//直接malloc開

if (startfree == null)//開闢失敗就找-

}endfree = null;

//試著呼叫一級空間配置器

startfree = (char*)_mallocalloctemplate::allocate(bytestoget);

}heapsize += bytestoget;

endfree = startfree + bytestoget;

return chunalloc(size, nobjs);//再去找

}} static void* refill(size_t n)

cur->freelistlink = null;

return ret;

} public:

static void* allocate(size_t n)

obj* volatile* myfreelist = freelist + freelistindex(n); //定位下標 用二級指標指向這塊記憶體

obj* ret = *myfreelist;

if (ret == null)

*myfreelist = ret->freelistlink;//改變一級指正的位置讓裡面放下乙個空閒空間

return ret;

} static void deallocate(void* p, size_t n)

obj* volatile* myfreelist = freelist + freelistindex(n);

obj* q = (obj*)p;

q->freelistlink = *myfreelist;

*myfreelist = q;

} };

template char* __defaultalloctemplate::startfree = null;

templatechar* __defaultalloctemplate::endfree = null;

templatesize_t __defaultalloctemplate::heapsize = 0;

templatetypename __defaultalloctemplate::obj* __defaultalloctemplate::freelist[__num_free_list];//告訴他是個型別引數

template>

class myalloctor

void operator delete(void *p,size_t n)

pointer _allocate(int _n, const void *)

//構造物件

void construct(pointer _p, const _ty& _v)//在指定的空間上構造物件

//析構物件

void destroy(pointer _p)//析構物件

//釋放記憶體

void deallocate(void *_p, size_t n)//釋放記憶體 };

int main()

具體結構如下圖

貌似二級空間配置器中的空間重頭到尾都沒看到他歸還給系統。那麼問題就是,記憶體池空間何時釋放?

對於這個問題,在回頭瀏覽一下原始碼及結構圖,你就會發現

大於128的記憶體,客戶程式deallocate之後會調free釋放掉,歸還給了系統。

但是呢...............

記憶體池中獲取的空間,最終,假定使用者都呼叫dealloc釋放調了,那麼他們又在**呢?

沒有還給系統,沒有在記憶體池,在自由鍊錶中。

got it:程式中不曾釋放,只是在自由鍊錶中,且配置器的所有方法,成員都是靜態的,那麼他們就是存放在靜態區。釋放時機就是程式結束。

因為真正可以在程式執行中就歸還系統的只有自由鍊錶中的未使用值,但是他們並不一定是連續的(使用者申請空間,釋放空間順序的不可控制性),所以想要在合適時間(eg一級配置器的handler中釋放,或者設定各閥值,分配空間量到達時處理),就必須保證釋放的空間要是連續的。保證連續的方案就是:跟蹤分配釋放過程,記錄節點信心。釋放時,僅釋放連續的大塊。

既然已經存在,而又被廣泛使用,那麼,整體的效率,以及和stl內部容器之間的使用配合還是沒問題的。

我們考慮幾種情況:

a. 使用者只需要無限的char型別空間,然而配置器中卻對齊到8,於是乎,整個程式中就會有7/8的空間浪費。

b.對於假定使用者申請n次8空間,將系統資源耗到一定程度,然後全部釋放了,自由鍊錶中的空間都是連續的。卻沒有釋放。

但是:使用者需要申請大於8的空間時,卻依舊沒有空間可用。

總結一下,stl對記憶體的請求與釋放

stl考慮到小型記憶體區塊的碎片問題,設計了兩級配置器,第一級配置器直接使用malloc和free,第二級配置器根據申請的空間的大小而採用不同的方法,當申請的空間大於128位元組時,直接呼叫呼叫第一級配置器,當申請的空間小於128位元組時,使用乙個memory pool的實現機制。 

sgi中預設使用的是第二級空間配置器。 

第二級空間配置器的實現機制:該配置器維護16個free_list,各自管理8,16,24,32,40….128位元組的小額區塊,當有這樣的配置需求時,將申請的空間提公升至8的倍數,定位到對應的free_list,直接從free_list取出一塊記憶體,(如果該free_list為空的話,呼叫refill函式,重新填充free_list,而refill函式呼叫chunk_alloc函式從記憶體池中申請空間)當客戶端歸還記憶體時,根據歸還記憶體的大小,將記憶體插入到對應的free_list上。

stl中的記憶體分配器實際上是基於空閒列表(free list)的分配策略,最主要的特點是通過組織16個空閒列表,對小物件的分配做了優化。 

1)小物件的快速分配和釋放。當一次性預先分配好一塊固定大小的記憶體池後,對小於128位元組的小塊記憶體分配和釋放的操作只是一些基本的指標操作,相比於直接呼叫malloc/free,開銷小。 

2)避免了記憶體碎片的產生。

釋放: 

大於128的記憶體,客戶程式deallocate之後會調free釋放掉,歸還給了系統。 

小於128的記憶體,程式中不曾釋放,只是在自由鍊錶中,且配置器的所有方法,成員都是靜態的,那麼他們就是存放在靜態區。釋放時機就是程式結束。

《STL剖析》 空間配置器(一)

sgi stl 的配置器與眾不同,也與標準規範不同,其名稱是 alloc 而非 allocator 而且不接受任何引數。一 sgi標準的空間配置器,std allocator 雖然 sgi 也定義有乙個符合部分標準 名為 allocator 的配置器,但 sgi 從未用過它,也不建議我們使用。主要原...

STL原始碼剖析 空間配置器

看過stl空間配置器的原始碼,總結一下 1 stl空間配置器 主要分三個檔案實現,stl construct.h 這裡定義了全域性函式construct 和destroy 負責物件的構造和析構。stl alloc.h檔案中定義了 一 二兩級配置器,彼此合作,配置器名為alloc.stl uninit...

STL原始碼剖析 空間配置器

allocator是空間配置器而不是記憶體配置器,空間不一定是記憶體,也可以是磁碟或其他輔助儲存介質。但sgi stl提供的配置器配置的物件是記憶體。sgi標準的空間配置器,std alloctor sgi定義了乙個符合部分標準,名為alloctor的配置器,效率不高,只把c 的 operator ...