本文已經(jīng)遷移到: http://cpp./cn:gc-allocator-and-boost-object-pool
C++內(nèi)存管理變革(4): boost::object_pool許式偉 (版權(quán)聲明) 這篇文章拖的有點久了。NeutralEvil 在3個月之前就在催促我繼續(xù)寫了。只是出于WinxGui完整性的考慮,我一直在刻意優(yōu)先去補(bǔ)充其它方面的文章,而不是讓人去誤會WinxGui是一個內(nèi)存管理庫了。:) 言歸正傳。我們在內(nèi)存池(MemPool)技術(shù)詳解已經(jīng)介紹了boost::pool組件。從內(nèi)存管理觀念的變革來看,這是是一個傳統(tǒng)的MemPool組件,盡管也有一定的改進(jìn)(但只是性能上的改進(jìn))。但boost::object_pool不同,它與我在C++內(nèi)存管理變革強(qiáng)調(diào)的觀念非常吻合??梢哉J(rèn)為,boost::object_pool是一種不通用的gc allocator組件。 我已經(jīng)多次提出gc allocator的概念。這里仍然需要強(qiáng)調(diào)一下,所謂gc allocator,是指具垃圾回收能力的allocator。C++內(nèi)存管理變革(1) 中我們引入了這個概念,但是沒有明確gc allocator一詞。 boost::object_pool內(nèi)存管理觀念boost::object_pool的了不起之處在于,這是C++從庫的層次上頭一次承認(rèn),程序員在內(nèi)存管理上是會犯錯誤的,由程序員來確保內(nèi)存不泄漏是困難的。boost::object_pool允許你忘記釋放內(nèi)存。我們來看一個例子: class X { … }; 如果boost::object_pool只是一個普通的allocator,那么這段代碼顯然存在問題,因為obj1的析構(gòu)函數(shù)沒有執(zhí)行,申請的內(nèi)存也沒有釋放。 但是這段代碼是完全正常的。是的,obj1的析構(gòu)確實執(zhí)行了,所申請內(nèi)存也被釋放了。這就是說,boost::object_pool既支持你手工釋放內(nèi)存(通過主動調(diào)用object_pool::destroy),也支持內(nèi)存的自動回收(通過object_pool::~object_pool析構(gòu)的執(zhí)行)。這正符合gc allocator的規(guī)格。 注:內(nèi)存管理更好的說法是對象管理。內(nèi)存的申請和釋放更確切的說是對象的創(chuàng)建和銷毀。但是這里我們不刻意區(qū)分這兩者的差異。 boost::object_pool與AutoFreeAlloc我們知道,AutoFreeAlloc不支持手工釋放,而只能等到AutoFreeAlloc對象析構(gòu)的時候一次性全部釋放內(nèi)存。那么,是否可以認(rèn)為boost::object_pool是否比AutoFreeAlloc更加完備呢? 其實不然。boost::object_pool與AutoFreeAlloc都不是完整意義上的gc allocator。AutoFreeAlloc因為它只能一次性釋放,故此僅僅適用特定的用況。然而盡管AutoFreeAlloc不是普適的,但它是通用型的gc allocator。而boost::object_pool只能管理一種對象,并不是通用型的allocator,局限性其實更強(qiáng)。 boost::object_pool的實現(xiàn)細(xì)節(jié)大家對boost::object_pool應(yīng)該已經(jīng)有了一個總體的把握?,F(xiàn)在,讓我們深入到object_pool的實現(xiàn)細(xì)節(jié)中去。 在內(nèi)存池(MemPool)技術(shù)詳解中,我們介紹boost::pool組件時,特意提醒大家留意pool::ordered_malloc/ordered_free函數(shù)。事實上,boost::object_pool的malloc/construct, free/destroy函數(shù)調(diào)用了pool::ordered_malloc, ordered_free函數(shù),而不是pool::malloc, free函數(shù)。 讓我們解釋下為什么。 其實這其中的關(guān)鍵,在于object_pool要支持手工釋放內(nèi)存和自動回收內(nèi)存(并自動執(zhí)行析構(gòu)函數(shù))兩種模式。如果沒有自動析構(gòu),那么普通的MemPool就足夠了,也就不需要ordered_free。既然有自動回收,同時又存在手工釋放,那么就需要區(qū)分內(nèi)存塊(MemBlock)中哪些結(jié)點(Node)是自由內(nèi)存結(jié)點(FreeNode),哪些結(jié)點是已經(jīng)使用的。對于哪些已經(jīng)是自由內(nèi)存的結(jié)點,顯然不能再調(diào)用對象的析構(gòu)函數(shù)。 我們來看看object_pool::~object_pool函數(shù)的實現(xiàn):
template <typename T, typename UserAllocator> 這段代碼不難理解,object_pool遍歷所有申請的內(nèi)存塊(MemBlock),并遍歷其中所有結(jié)點(Node),如果該結(jié)點不出現(xiàn)在自由內(nèi)存結(jié)點(FreeNode)的列表(FreeNodeList)中,那么,它就是用戶未主動釋放的結(jié)點,需要進(jìn)行相應(yīng)的析構(gòu)操作。 現(xiàn)在你明白了,ordered_malloc是為了讓MemBlockList中的MemBlock有序,ordered_free是為了讓FreeNodeList中的所有FreeNode有序。而MemBlockList, FreeNodeList有序,是為了更快地檢測Node是自由的還是被使用的(這實際上是一個集合求交的流程,建議你看看std::set_intersection,它定義在STL的<algorithm>中)。 C++內(nèi)存管理變革-系列文章
更多
0
|
|