STL原始碼剖析 空間配置器

2021-09-19 12:04:57 字數 2401 閱讀 3676

我:?????然後開始聊vector動態擴容,/(ㄒoㄒ)/~~

sgi stl的配置器與眾不同,名稱是alloc而非allocator。標準的allocator只是對操作符new和delete的一層薄薄的封裝,並沒有考慮到任何效率上的優化。

一般而言,我們習慣的c++記憶體配置操作和釋放操作是這樣的:

class foo ;

foo *pf=new foo;

delete pf;

new算式含兩個階段的操作:

::operator new配置記憶體。

呼叫foo::foo()構造物件內容。

delete算式也含有兩個階段的操作:

呼叫foo::~foo()將物件析構。

呼叫::operator delete將記憶體釋放。

stl allocator決定將這兩個階段的操作分開。配置器定義於之中,sgi的內含以下兩個檔案:

#include//負責記憶體空間的配置和釋放

#include//負責物件內容的構造和析構

我們直接來看alloc,sgi對此的設計哲學如下:

考慮到小型區塊所可能造成的記憶體破碎問題,sgi設計了雙層級配置器。

第一級配置器直接使用malloc()和free()。

第二級配置器則視情況採用不同的策略。當配置區超過128bytes時,視為足夠大,便呼叫第一級配置器,配置區小於128bytes時,視之過小,採用複雜的記憶體池整理方式。

我們來複習一下c++中new/delete和malloc/free的區別:

第一級配置器以malloc(),free(),realloc()等c函式執行實際的記憶體配置、釋放、重配置操作,並實現出類似c++ new-handler的機制(::operator new才有new-handler機制)。

new-handler機制:你可以要求系統在記憶體配置需求無法被滿足的時候,呼叫乙個你指定的函式,也就是在丟擲bad_alloc異常之前,會先呼叫由客端指定的處理例程。

sgi的做法是,在呼叫malloc和realloc不成功後,改呼叫oom_malloc()和oom_realloc(),這兩者都有內迴圈,不斷地呼叫「記憶體不足處理例程」,期望在某次呼叫之後,獲得足夠的記憶體而圓滿完成任務。但如果這個「記憶體不足處理例程」未被客端設定,就丟擲bad_alloc異常啦。(oom:out of memory)。

第二級配置器維護16個free-list,各自管理大小分別為8,16,24,32。。。128bytes的小額區塊。free-list的節點結構如下:

union obj
obj可以被視為乙個指標,指向相同形式的另乙個obj。

obj可以被視為乙個指標,指向實際區塊。

一物二用,不會為了維護鍊錶所必須的指標而造成記憶體的另一種浪費。由型別」union」可知指標free_list_link和陣列client_data共享一段大小為sizeof(union obj)=4的記憶體空間。當指標free_list_link指向下乙個節點時,client[0]內儲存的內容為下乙個節點的前乙個位元組大小的位址(實際上,現在陣列client_data並沒有使用到)。但當客端需要使用小額區塊,即使用client_data陣列的時候,free_list_link內儲存的下乙個節點的位址資料將被覆蓋掉,故而free-list也就不再指向他們。

當呼叫allocate()發現free_list中沒有可用區塊時,就呼叫refill(),準備為free_list重新填充空間。新的空間將取自記憶體池,由chunk_alloc完成,預設取得20個新區塊,但萬一記憶體池空間不足,獲得的區塊數可能小於20。

從記憶體池中取空間給free_list用,是chunk_alloc()的工作。

如果記憶體池水量足夠,就直接調出20個區塊返回給free_list。如果水量不足以提供20個區塊,但還足夠**乙個以上的區塊,就把能給出去的都給出去,如果一塊都給不出了,就用malloc()從heap中配置記憶體,新水量的大小為需求量的兩倍,再配上乙個隨著配置次數增加而愈來愈大的附加量。

例子:程式一開始,記憶體池水量為0,客端就呼叫chunk_alloc(32,20),於是malloc()配置40個32bytes區塊,其中第一塊交出去,剩下19塊給free_list[3]維護,餘下20塊給記憶體池。接下來客端再呼叫chunk_alloc(64,20),記憶體只夠提供20*32/64=10塊,那一塊給客端,剩下9塊給free_list[7]維護。再呼叫chunk_alloc(96,20),於是malloc()配置40+n(附加量)個96bytes區塊,其中第一塊給客端,剩下19塊給free_list[11]維護,餘20+n個區塊留給記憶體池。

等到整個system heap都不夠用了,malloc()行動失敗,就開始呼叫第一級配置器,它有out-of-memory處理機制。

以上就是stl的空間配置器的內容了。理解了stl空間配置,system heap。

感覺今天又學到一點了,共勉!!

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

STL原始碼剖析 空間配置器

由於物件的建立分為分配記憶體和呼叫建構函式兩部分,stl allocator使用alloc allocate 來分配記憶體,construct 構造物件。construct 函式只有乙個泛化的版本,destroy 函式有乙個泛化的針對迭代器的版本,destroy aux 根據是否需要呼叫析構函式進行...