STL記憶體管理器的分配策略

2021-08-03 22:33:04 字數 2523 閱讀 7532

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

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

STL配置器的記憶體分配策略

stl的幾個組成部分 1.容器 各種資料結構 2.演算法 各種常用演算法 3.迭代器 容器與演算法之間的聯合器,泛型指標 4.仿函式 協助演算法完成不同的策略的變化?5.介面卡 修飾或套接仿函式?6.配置器 分配空間管理 配置器的記憶體空間管理策略 一級配置器 對於大於128b的空間,使用一級配置器...

C C 記憶體管理器

c標準庫提供了malloc,free,calloc,realloc,c 標準庫還提供了new,new,delete,delete。這些用來管理記憶體,看起來夠用了,為啥還要自己寫乙個記憶體管理器呢?原因還是從效能考慮 例如malloc和new是出於通用性考慮的,能處理多執行緒情況 multithre...