STL記憶體池講解

2021-08-30 02:23:40 字數 4855 閱讀 9122

簡單說下:設計記憶體池的目的主要是為了解決在一些特殊的場合(比如:網路程式設計時接受資料報)頻繁的建立和銷毀、造成的大量的記憶體碎片和降低效率。

在stl的記憶體池中可以看到、它的實現是利用了乙個自由鍊錶陣列、obj** free_lists;陣列中每個元素都是乙個自由鍊錶的頭指標、它指向乙個由多個記憶體塊連成的鍊錶。另外、每個鍊錶中所包含的記憶體塊的大小是固定的、stl中是從8開始到128byte結束、塊與塊間的大小間隔也是8、也就是8、16、24、32、40、48、56、64、72、80、88、96、104、112、120、128。那麼free_lists鍊錶陣列的大小也就是16。

先看一下我按照stl中的方案實現的記憶體池**:

//標頭檔案

#pragma once

#include #include #include using namespace std;

class cmemorypool

; obj** freelists;

char* startpos;

char* endpos;

unsigned int heapsize; //記憶體池分配的總大小

char** ptrtoheadeachalloc; //每次記憶體池向系統申請空間時這裡會記錄乙個首位址

size_t maxalloctime; //最大次數、用於記錄

size_t alloctime; //向系統申請空間的次數

public:

cmemorypool(unsigned nalign = 8,unsigned nmaxbytes = 128,unsigned nnumberofaddnodeeachtime = 20);

virtual ~cmemorypool(void);

private:

size_t round_up(size_t size)

size_t freelist_index(size_t size)

protected:

void* allocate(size_t size);

void* refill(size_t size);

char* blockalloc(size_t size, size_t& num);

void deallocate(void* ptr, size_t size);

void close();

};

//原始檔

#include "memorypool.h"

cmemorypool::cmemorypool(unsigned nalign,unsigned nmaxbytes ,unsigned nnumberofaddnodeeachtime)

:align(nalign),maxbytes(round_up(nmaxbytes)),numberoffreelist(nmaxbytes / nalign),

numberofaddnodeeachtime(nnumberofaddnodeeachtime),

freelists(new obj*[numberoffreelist]),startpos(null),endpos(null),heapsize(0),

ptrtoheadeachalloc((char**)malloc(50)),maxalloctime(50),alloctime(0)

cmemorypool::~cmemorypool(void)

void cmemorypool::close()

} if(ptrtoheadeachalloc)

if(freelists)

}//分配指定大小記憶體

void* cmemorypool::allocate(size_t size)

size_t index = freelist_index(size);

obj* node = freelists[index];

if(node)

return refill(round_up(size));

}//填充乙個自由鍊錶、返回頭

void* cmemorypool::refill(size_t size)

elseelse

} return block; }}

//分配記憶體塊

char* cmemorypool::blockalloc(size_t size, size_t& num)

else if(totalsize >= size)else

startpos = (char*)malloc(allocsize);

if(startpos == null)

}//執行到這、說明記憶體分配失敗且沒有足夠大的空閒節點

throw bad_alloc();

}else

maxalloctime += 50;

}ptrtoheadeachalloc[alloctime++] = startpos;

heapsize += allocsize;

endpos = startpos + allocsize;

return blockalloc(size,num);

} }}//釋放記憶體

void cmemorypool::deallocate(void* ptr, size_t size)

else

}

簡述一下它的實現步驟:

1、最開始的時候因為不知道要分配多大的空間、所以這是startpos - endpos為0、也就是記憶體池是空的。在分配時先到對應的free_list(申請空間與塊大小最接近的鍊錶)中尋找、是否有空間、如果沒有再去記憶體池中尋找、然而這時記憶體池中也沒有空間、那麼就只能向系統申請空間了。如果成功:則進行相應的記憶體分配、並且將剩餘部分記憶體(有一部分記憶體池自己留下了)分塊「掛」在對應的free_list上。

2、如果在記憶體池向系統申請空間時失敗了、那麼為了「應急」就查詢塊大小比使用者所申請的空間還大的鍊錶中是否存在節點塊、如果存在直接將它「拿下來」放到記憶體池中(也就是調整startpos和endpos)、再重新分配(這時記憶體池中已經有了空間所以就可以直接將它提供給使用者了)。

有幾點需要注意:

1、為什麼obj節點要使用共用體?

其意思就是:

struct obj

;union obj

;

這裡再說下:柔性陣列

struct node

;

這時node的大小是4byte、因為b陣列0長度。但是b陣列的位址在node位址的下面也就是:

node* n = (node*)malloc(sizeof(node) + 4);  這時連續多出來的4個位元組的首位址就是b、還有:

char str[100];

node* p = (node*)str;字串的前4個位元組被a占用、後面的都被b所使用。

結構體柔性陣列的位址是在整個node之後的、但是共用體柔性陣列的位址就是node的首位址、柔性陣列可表示可變長度的空間、所以上面obj中的data就是為了適應不同的塊大小。因為它可以表示可變長度。

2、塊大小必須大於或等於乙個指標的大小、也就是align大於等於4。

那是因為每個節點其實就是分配的記憶體塊的頭部分的4個位元組、如果記憶體塊本身不能大於4那麼也就不夠將空間轉換為obj。

下面是根據記憶體池實現的分配器:

#pragma once

#include #include "memorypool.h"

/*模板不支援分離編譯*/

templateclass cmyallocator : public cmemorypool

;templatecmyallocator::cmyallocator(unsigned nalign,unsigned nmaxbytes,unsigned nnumberofaddnodeeachtime)

:cmemorypool(nalign,nmaxbytes,nnumberofaddnodeeachtime)

templatecmyallocator::~cmyallocator(void)

templatet* cmyallocator::allocate()

templatet* cmyallocator::allocate(size_type numoft)

templatevoid cmyallocator::deallocate(t* ptr)

templatevoid cmyallocator::deallocate(t* ptr,size_type num)

templatevoid cmyallocator::construct(t* ptr)

templatevoid cmyallocator::construct(t* ptr,const t& value)

templatevoid cmyallocator::destroy(t* ptr)

templatevoid cmyallocator::destroy(t* first,t* last)

}templatevoid cmyallocator::close()

stl記憶體池學習(二) 走近記憶體池

這一節學習基礎知識 所用到的資料結構。首先看記憶體池的介面 code ifndef mem pool h define mem pool h static size t freelist index size t bytes static size t round up size t bytes s...

stl記憶體池學習(一) 記憶體池初認識

序號 0123 4567 891011 1213 1415 串接區塊816 2432 4048 5664 7280 8896 104112 120128 範圍1 8 9 16 17 24 25 32 33 40 41 48 49 56 57 64 65 72 73 80 81 88 89 96 97...

stl記憶體池學習(一) 記憶體池初認識

序號 0123 4567 891011 1213 1415 串接區塊816 2432 4048 5664 7280 8896 104112 120128 範圍1 8 9 16 17 24 25 32 33 40 41 48 49 56 57 64 65 72 73 80 81 88 89 96 97...