stl記憶體管理

2022-08-12 09:18:13 字數 2396 閱讀 2004

stl提供了很多泛型容器,如vector,list和map。程式設計師在使用這些容器時只需關心何時往容器內塞物件,而不用關心如何管理記憶體,需要用多少記憶體,這些stl容器極大地方便了c++程式的編寫。例如可以通過以下語句建立乙個vector,它實際上是乙個按需增長的動態陣列,其每個元素的型別為int整型:

stl::vectorarray;

擁有這樣乙個動態陣列後,使用者只需要呼叫push_back方法往裡面新增物件,而不需要考慮需要多少記憶體:

array.push_back(10); array.push_back(2);

vector會根據需要自動增長記憶體,在array退出其作用域時也會自動銷毀占有的記憶體,這些對於使用者來說是透明的,stl容器巧妙的避開了繁瑣且易出錯的記憶體管理工作。

隱藏在這些容器後的記憶體管理工作是通過stl提供的乙個預設的allocator實現的。當然,使用者也可以定製自己的allocator,只要實現allocator模板所定義的介面方法即可,然後通過將自定義的allocator作為模板引數傳遞給stl容器,建立乙個使用自定義allocator的stl容器物件,如:

stl::vectorarray;

大多數情況下,stl預設的allocator就已經足夠了。這個allocator是乙個由兩級分配器構成的記憶體管理器,當申請的記憶體大小大於128byte時,就啟動第一級分配器通過malloc直接向系統的堆空間分配,如果申請的記憶體大小小於128byte時,就啟動第二級分配器,從乙個預先分配好的記憶體池中取一塊記憶體交付給使用者,這個記憶體池由16個不同大小(8的倍數,8~128byte)的空閒列表組成,allocator會根據申請記憶體的大小(將這個大小round up成8的倍數)從對應的空閒塊列表取表頭塊給使用者。

這種做法有兩個優點:

1)小物件的快速分配。小物件是從記憶體池分配的,這個記憶體池是系統呼叫一次malloc分配一塊足夠大的區域給程式備用,當記憶體池耗盡時再向系統申請一塊新的區域,整個過程類似於批發和零售,起先是由allocator向總經商批發一定量的貨物,然後零售給使用者,與每次都總經商要乙個貨物再零售給使用者的過程相比,顯然是快捷了。當然,這裡的乙個問題時,記憶體池會帶來一些記憶體的浪費,比如當只需分配乙個小物件時,為了這個小物件可能要申請一大塊的記憶體池,但這個浪費還是值得的,況且這種情況在實際應用中也並不多見。

2)避免了記憶體碎片的生成。程式中的小物件的分配極易造成記憶體碎片,給作業系統的記憶體管理帶來了很大壓力,系統中碎片的增多不但會影響記憶體分配的速度,而且會極大地降低記憶體的利用率。以記憶體池組織小物件的記憶體,從系統的角度看,只是一大塊記憶體池,看不到小物件記憶體的分配和釋放。

實現時,allocator需要維護乙個儲存16個空閒塊列表表頭的陣列free_list,陣列元素i是乙個指向塊大小為8*(i+1)位元組的空閒塊列表的表頭,乙個指向記憶體池起始位址的指標start_free和乙個指向結束位址的指標end_free。空閒塊列表節點的結構如下:

union obj ;

這個結構可以看做是從乙個記憶體塊中摳出4個位元組大小來,當這個記憶體塊空閒時,它儲存了下個空閒塊,當這個記憶體塊交付給使用者時,它儲存的時使用者的資料。因此,allocator中的空閒塊鍊錶可以表示成:obj* free_list[16];

allocator分配記憶體的演算法如下:

演算法:allocate 輸入:申請記憶體的大小size 輸出:若分配成功,則返回乙個記憶體的位址,否則返回null      } else }

重新填充演算法:

演算法: refill 輸入:記憶體塊的大小size 輸出:建立空閒塊鍊錶並返回第乙個可用的記憶體塊位址    }

塊分配演算法

演算法:chunk_alloc 輸入:記憶體塊的大小size,預分配的記憶體塊塊數nobj(以引用傳遞) 輸出:一塊連續的記憶體區域的位址和該區域內可以容納的記憶體塊的塊數       else if(記憶體池中不夠分配nobj個記憶體塊,但至少可以分配乙個)      else       }       更新end_free為start_free+total_bytes,heap_size為2倍的total_bytes;       呼叫chunk_alloc(size,nobj); }

假設這樣乙個場景,free_list[2]已經指向了大小為24位元組的空閒塊鍊錶,如圖1所示,當使用者向allocator申請21位元組大小的記憶體塊時,allocaotr會首先檢查free_list[2]並將free_list[2]所指的記憶體塊分配給使用者,然後將表頭指向下乙個可用的空閒塊,如圖2所示。注意,當記憶體塊在鍊錶上是,前4個位元組是用作指向下乙個空閒塊,當分配給使用者時,它是一塊普通的記憶體區。

圖1   某時刻allocator的狀態

圖2 分配24位元組大小的記憶體塊

STL 記憶體管理

stl有很多種allocator,根據c 的標準,stl的allocator把物件的申請和釋放分為四個步驟 1 申請記憶體空間,對應的函式是allocator allocate 2 執行建構函式,對應的函式是allocator construct 3 執行析構函式,對應的函式是allocator d...

STL記憶體管理

linux記憶體分配管理 實現自己的malloc stl是一套非常高效的c 庫,提到記憶體管理,怎麼能少了他呢,花了近一天的時間來剖析這個。stl記憶體分配分為兩級,為什麼分為兩級,就比如你為了買一根普通的皮帶,去漢正街批發市場,別人不一定賣給你 親身經歷 只有一次性購買大量的貨才會去批發市場,商家...

STL記憶體管理

過年在家無事看了 stl原始碼剖析 開學了將看過的東西總結一下,以防忘記。先從stl的記憶體管理開始總結。掌管stl記憶體控制的是乙個叫空間介面卡 alloc 的東西。stl有兩個空間介面卡,sgi標準空間介面卡 allocate 和sgi特殊的空間介面卡 alloc 前者只是對c 的new和del...