搞定IPhone應用的內存泄露 – iPhone手機開發技術文章 iPhone軟體開發教學課程

IPhone上木有垃圾回收,動態申請的內存要自己記得釋放,此文自己總結一下可能出現內存泄露的各種情況,以及檢測方法。
 
內存泄露說白瞭,就是有這樣一塊動態申請的內存,但木有任何一個指針指向它。
 
舉例來說,在C++中:
 
1. MyClass * foo = new MyClass; 
2. foo = NULL;
 
類似地在objective-C中:
 
1. MyClass *foo = [[MyClass alloc] init]; 
2. foo = nil;//內存泄露瞭!
 
 
或者有這樣一個類:
 
1. @interface Foo : NSObject 
2. {} 
3. @end 
4. 
5. @implementation Foo 
6. -(id) init 
7. { 
8.         if ((self = [super init])) { 
9.                 NSMutableString * string = [[NSMutableString alloc] initWithString:@"Leaker!!!"]; 
10.                 string = nil;//泄露瞭!這句之後那個字符串對象應用退出之前不會被釋放。
11.         } 
12.         return self; 
13. } 
14. – (void) dealloc 
15. { 
16.         [super dealloc]; 
17. } 
18. @end
 
出現內存泄露會怎樣?
答:很小的泄露,沒事!應用退出的時候所用內存都會被清理,包括泄露的,而且IPhone應用不會申請到共享內存,不會波及到整個系統,不會出現系統范圍的內存泄露。要是泄露的比較多,而且反復不停地出現內存泄露,頂多應用崩潰掉。不過想發佈到AppStore的話,有內存泄露一般會被蘋果拒絕……。
 
先來看看IPhone裡內存是怎麼管理的,首先:木有自動垃圾回收!其次:有引用記數!
NSObject對象有個屬性:retainCount,所以所有對象都要繼承自NSObject,才有統一的引用計數…。
 
然後牢記記住下面8件事:
• 1 這個retainCount == 0的時候,對象的dealloc方法會被調用,對象就被釋放瞭。
• 2 永遠不要顯示調用dealloc方法
• 3 [obj retain]; // obj.retainCount++ 引用記數+1
• 4  [obj release]; // obj.retainCount– 引用記數-1
• 5 MyClass * obj = [[MyClass alloc] init];// obj.retainCount = 1 初值為1
• 6 對於有retain特性的屬性比如下面這個:
1. @interface MyClass : NSObject { 
2.   NSObject* foo; 
3. } 
4. @property (noatomic,retain) NSObject * foo; 
5. @end 
6. 
7. @implementation MyClass 
8. @synthesize foo; 
9. … 
10.   //下面兩行正確的寫法 
11.   self.foo = bar;// [foo release]; foo = bar; [foo retain]; 會發一個release給原來的對象,發一個retain 給新對象 
12.   self.foo = nil;// [foo release]; 會發一個release 消息給對象 
13. 
14.   //下面一行寫法不對 
15.   foo = bar;// 沒發release給foo 沒發retain給bar ,這種寫法是不對的。 
16. … 
17. @end
  參考:
蘋果的文檔 和 具體實現的解釋

• 7 對於stringWithString 這種方法創造的對象,一個Runloop結束時,對象會被發送一個release消息,需要註意的有兩點,一是註意理解Runloop,避免Runloop結束後對象被釋放瞭卻又使用對象,二是 如果用instruments工具檢測內存泄露,這種使用autorelease的情況也會被當做內存泄露處理,註意識別……。
• 8 對於NSMutableArray這種類,當addObject的時候,相應被加入array中的那個對象的引用計數會被+1,當array本身釋放時,它會先給array中的所有對象發一個release消息。www.aiwalls.com
 
可以用Instruments檢測內存泄露,裡各種各樣的工具,用Leaks。
用起來很簡單:用Xcode(4.3)打開相應的項目,Product->Profile,選Leaks工具。 之後會動態地記錄應用運行過程中,有哪些地方出現內存泄露。 需要註意的地方有二:
1 對於被autorelease的對象,Leak工具也會視其為泄露,自己知道沒問題就行。
2 記得點開Extended Detail ,對於每一出泄露,可以在這裡看到調用堆棧,雙擊調用堆棧中的某一項,可以直接定位到代碼,便於查錯跟修改。 情況如下兩個圖:


作者:dawn110110

發佈留言