1.內存池
程序員在使用C++中的動態內存分配器時,new/delete, malloc/free等操作時,可能會出現以下問題:
- Memory Leak:new一塊空間,但中間拋出錯誤,最後沒有釋放成功,導致memory leak;這個問題可以採用智能指針auto_ptr, shared_ptr, unique_ptr來解決
- Mismatching Operators:new和delete沒有配對使用,如new數組時,沒有調用delete [] array,一個ptr被多次delete等錯誤操作
- Fragmentation:當多次調用new和delete時,會讓heap上產生大量的外部碎片
- Long execution time:new/delet操作或者庫函數malloc/free有可能需要系統調用,那麼操作的overhead就會比較大
- 預先申請好一塊內存區域,並把它分成定長的塊,當buffer中的內存不夠時:使用類似vector的擴張方法,每次內存不夠時,重新申請一塊長度爲已有內存兩倍的內存塊。
- 每次需要內存申請時,將一塊尚未分配的塊返回。每次釋放時,將傳入的內存塊重新標記爲未分配。
實現方法:內部維護多個定長內存池,每次找到最小的能滿足條件的內存池進行內存分配。如果申請的內存大於所有的內存池大小,則直接調用malloc()
如:分別維護1,2,4,8,16,32,64,128,256,512,1024bytes的定長內存池,對於每一個內存申請向上對齊到2的整次冪後分配對應大小的內存塊,此時空間最多浪費一倍,效率低於定長內存池
第一級配置器直接調用C的內存分配函數malloc()及realloc(),如果調用失敗則執行oom_malloc()
第二級配置器的做法是,如果區塊夠大,超過128bytes時,就移交第一級配置器處理。當區塊小於128bytes時,則以不定長內存池管理。
不定長內存池中維護16個定長內存池,大小分別爲8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128bytes,將所需的內存向上對齊至8的倍數後交由對應的定長內存池分配
所有stl容器默認使用上述stl::alloc進行內存管理