OC的內存管理

1.內存泄露

一般我們常說的內存泄漏是指堆內存的泄漏。堆內存是指程序從堆中分配的,大小任意的(內存塊的大小可以在程序運行期決定),使用完後必須顯式釋放的內存。應用程序一般使用malloccallocrealloc等函數(C++中使用new操作符)從堆中分配到一塊內存,使用完後,程序必須負責相應的調用freedelete釋放該內存塊,否則,這塊內存就不能被再次使用,我們就說這塊內存泄漏了。

2. 內存管理

堆中的內存都是手動開闢和手動釋放的。因此我們要時刻統計堆的指針有哪些是指向同一個的。再釋放時,確認所有指向這個堆的指針,都已經用完了,不再使用。但這個存在先天的不足,畢竟程序員在統計指針是否用完時,受到多方面的影響而不能正確統計,程序在聯合開發的時候,指向同一個的堆的指針就很難統計,因此必須有一個合理的方法來管理內存。

3. 理解內存管理到底幹了什麼?

OC中的內存管理實際上就是一種PV操作,就是對計數器的加減操作。基類NSObject存在一個計數器retainCount,並會被子類所繼承。alloc創建對象時,計數器+1retain純粹的計數器+1release將計數器減1,不是真的free掉一個對象,release時本着個人顧個人的原則。

4. release原則(黃金法則)

當我們用allocretainnewcopymutablecopy這些函數創建地址付給指針時,需要用release或者autorelease釋放。釋放的時候,每個指針誰創建的誰釋放,不能去釋放別人創建的指針。

5. 成員變量爲對象的set函數

一個類的成員變量爲另一個類的對象時,爲了考慮內存管理,set函數的一般寫法,以Car類擁有Engine對象作爲成員變量爲例:

-(void)setEngine:(Engine *)newengine

{

if(engine!=newengine){ //判斷是否自我賦值

[engine release]; //若爲對象賦新值,先release舊的

engine=[newEngine retain]; //賦新值且retain一下計數器+1

}

return;

}

 

這個set函數充分的考慮到了,自我賦值和對象取新值的情況,engine爲空時,[engine release]執行一次,但不會產生效果,所以不會出現錯誤。因爲OC在創建對象時,成員變量默認爲nil[nil release]能夠執行,但是沒有效果,即不會對計數器產生影響。但是存在一個問題,就是賦新值後retain後,使用完成後會發現無法對其release,因爲car類對象一直使用着這個值,car對象銷燬,才執行retain一次,減少engine計數器一次。因此必須重寫Car類的dealloc函數,在car對象釋放時,release一下engine,以對應set函數中的retain,滿足黃金法則。

重寫的dealloc函數爲:

-(void)dealloc //car的對象釋放時,自動調用,類似析構函數

{

[engine release]; //self.engine=nil;作用相同(調用set函數)

[surper dealloc]; //模擬C++析構時,調用父類的析構函數

return;

}

6. 特殊成員變量的點語法

不同於普通變量,setget函數封裝應爲:

@property (retain) Engine * engine;

@synthesize engine;

這樣就不用麻煩的自己書寫set函數了。一個類的成員是另一個類時,此時 set函數會與以前的普通成員邊量set函數大有不同,set函數書寫爲內存 管路版本使用時,一定要重寫dealloc函數,處理成員對象的最後一次release

7. atuoreleaseatuoreleasepool

新版的自動釋放池寫法爲;

@autoreleasepool

{

}

釋放池作爲一個關鍵字存在,老版本的釋放池的書寫更易於理解,寫法如下:

NSAutorelease *pool = [[NSAutoreleasePool alloc]init];

…………

[pool release];

可以將pool看爲一個數組,將relase的對象裝在這個數組中,等到釋放池 釋放的時候,才把池中的對象全部執行一次release

8. 以對象dog爲例,使用自動釋放池release

[dog autorelease]; //自動釋放 延遲釋放

這裏是將dog地址添加到pool中,pool執行release時,才把池中的對象全 部執行一次release。在這之前,計數器並沒有真正的減一,pool釋放的時 dog的計數器纔會真正的減一。

9. 不到萬不得已的時候,千萬不要用autoreleasepool

IOS中每一個觸發週期,系統都會自動創建一個自動釋放池,在週期結束時, 就會釋放這個poolautorelease自動匹配最近的一個pool,我們並不能控 制其在我們想要釋放的時候才釋放。

+函數創建一個對象時,並不能確定何時釋放對象,因此我們在pool釋放時, 再釋放這個對象,避免錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章