學OC,肯定知道內存管理機制的原則。這里說說某些特殊的情況。
之前曾說,NSString的計數器比較特殊,大家注意下。
今天說另外一種,也是比較糾結的,以至於朋友都說這是OC BUG。。。
創建一個Class:
//H #import <Foundation/Foundation.h> @interface Car : NSObject - (void)show; @end //M #import "Car.h" @implementation Car - (void)show;{ NSLog(@"exec Finished!!!"); } @end
很簡單的show方法,確認Car類是否被free;
運行方法:
Car *car = [[Car alloc] init]; [car show]; [car release]; [car show]; NSLog(@"car retainCount:%d", [car retainCount]);
某些人可能一眼看出,執行未完成就會Crash;
但事實是,毫無Crash征兆,並且retainCount printf 1;
為什么會這樣??經過與幾個基友討論,得出以下結論:
1.car堆被標記,即release執行完成,但因為不是立即釋放,所以內存還存在;
2.存在棧中的car指針不由我們控制,同樣未釋放。
所以,給car指針指向的那塊內存發送show消息時,又得到了結果。
既然不是OC的BUG,那如果避免?
在我們的項目中,肯定不會出現這樣的問題,因為當堆被標記,有新創建的OBJ,會自動占用掉。
可以這樣模擬:
Car *car = [[Car alloc] init]; [car show]; [car release]; for (int i = 0; i < 1000; i++) { @autoreleasepool { NSString *str = [NSString stringWithFormat:@"X%d", i]; NSLog(@"%@", str); } } [car show]; NSLog(@"%d", [car retainCount]);
此時,不等運行到顯示car的retainCount,已經Crash;
符合我們的結論;
如何避免就是大家熟悉的,在release后再設置nil即可;
其他的內存方面就不說了,只說奇葩的部分!!不對的地方請指出,謝謝。
