摘要:C++編程語言沒有提供完善的自動(dòng)垃圾回收機(jī)制,大型的復(fù)雜的程序設(shè)計(jì)經(jīng)常發(fā)生內(nèi)存泄露甚至程序崩潰的現(xiàn)狀,針對(duì)這種情況分析了利用C++標(biāo)準(zhǔn)庫和boost庫實(shí)現(xiàn)自動(dòng)垃圾回收的幾種方法并分析其優(yōu)缺點(diǎn)。
關(guān)鍵詞:C++;智能指針;自動(dòng)垃圾回收
中圖分類號(hào):TP312文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):1009-3044(2008)34-2007-02
How to Implement Garbage Auto-collection with C++
CHEN Long-de, BI Hai-bin
(Jiangnan Institute of Computing Technology, Wuxi 214083, China)
Abstract: The C++ language does not supply a perfect garbage auto-collection mechanism,so memory leak oftenoccur in complex programe design, this paper implements the garbage auto-collection with C++ standard library , C++ boost library and simplely evaluatesthese methods
Key words: C++; smart pointer; garbage Auto-Collection
1 引言
指針是C++語言中一種非常有效的內(nèi)置數(shù)據(jù)類型,常利用其進(jìn)行堆內(nèi)存分配 ,當(dāng)需要內(nèi)存時(shí)用new操作符在堆空間上開辟一塊空間,當(dāng)所申請(qǐng)內(nèi)存不再需要時(shí)用delete操作符釋放掉,相當(dāng)于一種手動(dòng)的垃圾回收,借助于new和delete對(duì)內(nèi)存的操作,可以方便地手工管理內(nèi)存、高效地使用內(nèi)存。但使用new 申請(qǐng)內(nèi)存后,由于程序的復(fù)雜性,特別是比較大型的程序設(shè)計(jì)中,常常忘記用匹配的delete在恰當(dāng)?shù)臅r(shí)候釋放內(nèi)存,這時(shí)候,這種new 內(nèi)存操作的單獨(dú)使用,會(huì)造成內(nèi)存資源的泄露和枯竭,嚴(yán)重影響系統(tǒng)的性能,甚至造成系統(tǒng)崩潰。綜上所述,實(shí)現(xiàn)自動(dòng)垃圾回收具有一定的實(shí)際意義。
2 基于智能指針的垃圾回收機(jī)制
2.1 基于std::auto_ptr的垃圾回收機(jī)制
在C++的標(biāo)準(zhǔn)庫中提供了一種智能指針auto_ptr,它保證當(dāng)異常擲出時(shí)分配的對(duì)象即new操作符分配的對(duì)象能被自動(dòng)銷毀,內(nèi)存能被自動(dòng)釋放。
2.1.1 基于std::auto_ptr垃圾回收原理
auto_ptr 雖然名稱叫做智能指針,但是事實(shí)上它是一個(gè)模板類,當(dāng)你實(shí)例化auto_ptr對(duì)象時(shí),對(duì)它進(jìn)行初始化的方法是用一個(gè)指針指向動(dòng)態(tài)分配的對(duì)象,下面是實(shí)例化和初始化auto_ptr對(duì)象的例子:
#include<memory>
#include<string>
Using namespace std;
Void func()
{
Auto_ptr<string> pstr(new string);
*pstr = \"hello world\";
pstr->size();
}
這時(shí)候,你可以像使用普通的對(duì)象指針一樣使用這個(gè)實(shí)例化的智能指針對(duì)象pstr。而當(dāng)pstr的析構(gòu)函數(shù)執(zhí)行時(shí),它會(huì)刪除構(gòu)造pstr期間創(chuàng)建的串指針,我們不必手動(dòng)調(diào)用pstr的析構(gòu)函數(shù),它會(huì)自動(dòng)調(diào)用。
2.1.2 基于auto_ptr的自動(dòng)垃圾回收的優(yōu)缺點(diǎn)
auto_ptr的優(yōu)點(diǎn)就是使用簡(jiǎn)單,除了實(shí)例化auto_ptr的時(shí)候和一般的new指針語法上有所區(qū)別以外,其他的和使用一般的指針是一樣的,使用起來很方便。
auto_ptr的缺點(diǎn)是不能將auto_ptr對(duì)象作為STL容器的元素,C++標(biāo)準(zhǔn)明確禁止這樣做,否則可能會(huì)碰到不可預(yù)見的結(jié)果,其次不支持將數(shù)組作為auto_ptr的參數(shù),因?yàn)閍uto_ptr的析構(gòu)函數(shù)只對(duì)非數(shù)組類型起作用。所以數(shù)組不能被正確摧毀的話,程序的行為是不明確的。
2.2基于boost庫的智能指針的垃圾回收機(jī)制
2.2.1 boost庫常用的智能指針簡(jiǎn)介
boost::scoped_ptr 用于確保能夠正確地刪除動(dòng)態(tài)分配的對(duì)象。scoped_ptr 有著與auto_ptr類似的特性,而最大的區(qū)別在于它不能轉(zhuǎn)讓所有權(quán)而auto_ptr可以。
boost::shared_ptr ,幾乎所有稍微復(fù)雜點(diǎn)的程序都需要某種形式的引用計(jì)數(shù)智能指針。這些智能指針讓我們不再需要為了控制被兩個(gè)或多個(gè)對(duì)象共享的對(duì)象的生存期而編寫復(fù)雜的邏輯。當(dāng)引用計(jì)數(shù)降為零,沒有對(duì)象再需要這個(gè)共享的對(duì)象,這個(gè)對(duì)象就自動(dòng)被銷毀了。
boost::weak_ptr 是 shared_ptr 的觀察員,它不會(huì)干擾shared_ptr所共享的所有權(quán)。當(dāng)一個(gè)被weak_ptr所觀察的shared_ptr 要釋放它的資源時(shí),它會(huì)把相關(guān)的 weak_ptr的指針設(shè)為空。
2.2.2 基于boost::shared_ptr的自動(dòng)垃圾回收
shared_ptr 是一種引用計(jì)數(shù)智能指針,可以分為插入式(intrusive)和非插入式(non-intrusive)兩類。前者要求它所管理的類提供明確的函數(shù)或數(shù)據(jù)成員用于管理引用計(jì)數(shù)。這意味著在類的設(shè)計(jì)時(shí)就必須預(yù)見到它將與一個(gè)插入式的引用計(jì)數(shù)智能指針一起工作,或者重新設(shè)計(jì)它。非插入式的引用計(jì)數(shù)智能指針對(duì)它所管理的類沒有任何要求。引用計(jì)數(shù)智能指針擁有與它所存指針有關(guān)的內(nèi)存的所有權(quán)。沒有智能指針的幫助,對(duì)象的共享會(huì)存在問題,必須有人負(fù)責(zé)刪除共享的內(nèi)存。誰負(fù)責(zé)?什么時(shí)候刪除?沒有智能指針,你必須在管理的內(nèi)存之外增加生存期的管理,這意味著在各個(gè)擁有者之間存在更強(qiáng)的依賴關(guān)系。換言之,沒有了重用性并增加了復(fù)雜性,使用shared_ptr智能指針,當(dāng)引用計(jì)數(shù)降為零,沒有對(duì)象再需要這個(gè)共享的對(duì)象,這個(gè)對(duì)象就自動(dòng)被銷毀了。
2.2.3 基于boost::shared_ptr自動(dòng)垃圾回收的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)是首先它改進(jìn)了基于auto_ptr的,不能將auto_ptr對(duì)象作為STL容器的元素的這個(gè)缺點(diǎn),另外一個(gè)優(yōu)點(diǎn)是它更適合管理對(duì)象被若干個(gè)對(duì)象共享的復(fù)雜問題。
缺點(diǎn)是我們相當(dāng)于拋棄了基本的指針的使用,而shared_ptr的使用相對(duì)復(fù)雜,我們的程序沒有了new和delete,可能廣大程序員短時(shí)間難以接受的。
3 基于boost::object_pool的垃圾回收機(jī)制
3.1 boost:: object_pool實(shí)現(xiàn)垃圾回收原理
boost::pool每次向系統(tǒng)申請(qǐng)一大塊內(nèi)存,然后分成同樣大小的多個(gè)小塊,形成鏈表連接起來。每次分配的時(shí)候,從鏈表中取出頭上一塊,提供給用戶。鏈表為空的時(shí)候,pool繼續(xù)向系統(tǒng)申請(qǐng)大塊內(nèi)存。
boost::object_pool與boost::pool的區(qū)別在于:pool需要指定每次分配的塊的大小,object_pool需要指定每次分配的對(duì)象的類型。
3.2 boost::object_pool的用法
Class X
{
……
};
Void func()
{
boost::obiect_pool<X>alloc;
X* obj1=alloc.construct();
X* obj2=alloc.construct();
Alloc.destroy(obj2);
}
細(xì)心的讀者肯定發(fā)現(xiàn)了,obj1的析構(gòu)函數(shù)沒有執(zhí)行,申請(qǐng)的內(nèi)存沒有釋放掉,但是沒有關(guān)系的,boost::obiect_pool既支持手工釋放即調(diào)用object::destroy(),也支持內(nèi)存自動(dòng)回收即object_pool::~object_pool()析構(gòu)函數(shù)的執(zhí)行。
3.3 基于boost:: object_pool垃圾回收的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)是使用靈活,既可以按照程序員的意愿進(jìn)行垃圾回收也可以自動(dòng)回收,缺點(diǎn)是它并不是一種通用型的垃圾回收機(jī)制,它只能管理一種對(duì)象。
4 結(jié)束語
利用C++標(biāo)準(zhǔn)庫的智能指針,boost庫的智能指針,以及boost的object_pool在一定的條件下可以實(shí)現(xiàn)垃圾自動(dòng)回收,但是顯然這幾種方法的局限性很大,而且對(duì)用戶也是不透明的,算不上完全的自動(dòng)。但是在某些具體的場(chǎng)合還是能起到一定的作用。
參考文獻(xiàn):
[1] Karlsson B,Beyond the C++ Standard Library: An Introduction to Boost[M].Addison-Wesley Professional,2005.
[2] 朱國(guó)仲,楊彬,布輝 自動(dòng)垃圾回收指針模板類的設(shè)計(jì)與實(shí)現(xiàn)[J].華北水利水電學(xué)院學(xué)報(bào),2006,27(2):73-75.
[3] 曾天慧,於時(shí)才,董榮輝,JAVA垃圾收集機(jī)制及性能調(diào)節(jié)[J].計(jì)算機(jī)工程與設(shè)計(jì),2006,27(1):3242-3247.
[4] Jones R,Lins R.垃圾收集[M].北京:人民郵電出版社,2004.