摘 要:合理地內(nèi)存管理機制能確保有效地管理內(nèi)存資源。在Objective-C程序中,必須確保所創(chuàng)建的對象在不再需要它們的時候被銷毀。Cocoa定義了內(nèi)存管理規(guī)則和原則使得正確管理應(yīng)用程序的內(nèi)存變得容易和可靠。
關(guān)鍵詞:Objective-C;內(nèi)存管理;應(yīng)用
中圖分類號:TP311.11
在編寫程序的過程中,有效和高效地管理內(nèi)存資源是程序開發(fā)人員需要著重考慮的事情,一方面是為了保證應(yīng)用程序的內(nèi)存消耗盡可能低,另一方面是為了防止內(nèi)存泄漏。為此,Cocoa定義了一些有助于內(nèi)存管理的規(guī)則和原則。內(nèi)存管理所要做的就是清理不用的內(nèi)存,以便內(nèi)存能夠再次利用,即以某些方式確定一個對象不再需要使用了,并且它占用的內(nèi)存能夠被回收。
1 Objective-C內(nèi)存管理規(guī)則
Cocoa提供了一種被稱為“引用計數(shù)”或“保留計數(shù)”的機制,內(nèi)存管理被放在對象創(chuàng)建與銷毀的生命周期中,該機制不同于C語言中有方法(malloc/free)直接操作內(nèi)存,也不同于GC語言自動管理內(nèi)存。實際上,這種內(nèi)存管理方式使得每一個對象都有一個引用計數(shù),當(dāng)對象被創(chuàng)建的時候,其引用計數(shù)為1;當(dāng)引用計數(shù)減少到0時,對象會被銷毀。
在Objective-C中,所有對象都被定義為指針;指針是一個特殊的變量,它里面存儲的數(shù)值被解釋成為內(nèi)存里的一個地址,如果使用不當(dāng),就會出錯或者造成內(nèi)存的泄露。因此,在進行內(nèi)存管理時,需要了解內(nèi)存管理規(guī)則。Objective-C內(nèi)存管理規(guī)則的主要內(nèi)容:(1)把對象視為內(nèi)存,只能釋放或自動釋放所擁有的對象。(2)當(dāng)使用含有alloc、new、copy的方法創(chuàng)建對象,便擁有該對象的所有權(quán);或者向?qū)ο蟀l(fā)送retain消息,也會擁有該對象的所有權(quán)。(3)當(dāng)不再使用對象時,向?qū)ο蟀l(fā)送release或autorelease消息,將會釋放對象的所有權(quán)。通常,在不適合立即回收對象的情況下才使用autorelease。(4)通過實現(xiàn)dealloc方法來釋放所擁有的實例變量。(5)自由釋放池(@autoreleasepool),即自動引用計數(shù)(ARC機制),這是一種半自動機制,可以手動設(shè)置或取消。自動內(nèi)存釋放使用@autoreleasepool關(guān)鍵字聲明一個代碼塊,當(dāng)代碼塊執(zhí)行完之后,對象都會自動調(diào)用一次release方法,同時對象的銷毀過程也得到了延遲(統(tǒng)一調(diào)用release方法)。
2 常見錯誤及對策
內(nèi)存泄露主要是指由于設(shè)計的失誤對某塊內(nèi)存失去控制,而這塊內(nèi)存不能被再次使用,導(dǎo)致了內(nèi)存的浪費。當(dāng)發(fā)生內(nèi)存泄露或別的內(nèi)存問題時會比較麻煩,因為編譯器不會自動發(fā)現(xiàn)這類錯誤,通常是在程序運行時才能捕捉到;同時,Objective-C 2.0后引入的ARC機制,也不能完全避免內(nèi)存泄露等問題。避免內(nèi)存問題、解決內(nèi)存泄露的辦法:(1)為了防止內(nèi)存泄露,當(dāng)使用alloc或copy創(chuàng)建了對象,或者使用retain保留了對象,我們都必須通過release方法釋放。(2)改寫dealloc方法,在需要的時候釋放內(nèi)存。(3)手動創(chuàng)建autoreleasepool,該方法使得無須等待系統(tǒng)釋放所創(chuàng)建的對象,便可告訴系統(tǒng)在代碼段結(jié)束時釋放對象。(4)大多數(shù)情況下,申請內(nèi)存的語句數(shù)量和釋放內(nèi)存的語句數(shù)量應(yīng)該相等。
3 應(yīng)用實例
以下是內(nèi)存管理的一個例子,首先定義了一個類Student,包含兩個實例變量name和age,自定義相應(yīng)的setter和getter方法,并手動管理內(nèi)存,該例子給出了一個內(nèi)存泄露的情況,并在最后給出解決方案。
3.1 Student類的接口文件的定義:
3.2 Student類的實現(xiàn)文件的定義:
3.3 主方法main的實現(xiàn)如下:
從運行結(jié)果發(fā)現(xiàn),當(dāng)對象stu的實例變量name被字符串s2=”Jacky”重新賦值,此時,原來定義的字符串s1不再使用,但是它的引用計數(shù)仍然為1,到最后它所占用的內(nèi)存都沒有被釋放。
導(dǎo)致這種問題的產(chǎn)生的根源在-(void)setName:方法上,當(dāng)[stu setName:s1]時,name擁有了s1的使用權(quán);接下來,當(dāng)用戶使用[stu setName:s2]來替換了原來s1的值時,并沒有對name發(fā)送release消息,那么name對于s1的使用權(quán)就沒有釋放,但此時name的值已被s2所取代,即此刻name擁有了s2的使用權(quán),而s1不再使用,而此時s1的引用計數(shù)仍為1,所占用內(nèi)存沒有正?;厥?,故產(chǎn)生了內(nèi)存泄露。
為了解決該內(nèi)存問題,我們在原來的-(void)setName:方法中,增加[name release];這行代碼(即原方法中被注釋掉的一行),該代碼使得原來name沒有正確釋放它所擁有的對象的使用權(quán)的問題得到解決,相應(yīng)的內(nèi)存管理過程也正確了。同時,需要說明的是,當(dāng)初次執(zhí)行[name release];時,name的值為nil,而在Objective-C程序中,向nil發(fā)送任何消息都不會報錯。
4 結(jié)束語
綜上,只要掌握了Objective-C中的內(nèi)存管理的正確方法和步驟,很多不必要的內(nèi)存問題和內(nèi)存泄露是完全可以避免的。
參考文獻:
[1]楊正洪,鄭齊心,李建國.Objective-C程序設(shè)計[M].北京:清華大學(xué)出版社,2011.
[2]Stephen G.Kochan著,林冀,范俊,朱奕欣譯.Objective-C程序設(shè)計(第4版)[M].北京:電子工業(yè)出版社,2012.
[3]Scott Knaster,Waqar Malik,Mark Dalrymple著,周慶成(譯).Objective-C基礎(chǔ)教程(第2版)[M].北京:人民郵電出版社,2013.
作者簡介:任艷(1982.04-),女,教師,講師,碩士研究生,研究方向:現(xiàn)代數(shù)據(jù)庫技術(shù)。
作者單位:蘇州高博軟件技術(shù)職業(yè)學(xué)院,江蘇蘇州 215100