[Note] Effective OC - Item 32~36

Chapter 5. Memory Management

<br />


Item 32: Beware of Memory Management with Exception-Safe Code

<br />
這一節(jié)講的是使用exception時存在的內存管理問題惊搏。
在Item21講NSError的使用時已經提到了宝恶,OC的設計并不是exception-safe的,因此不能普遍地使用exception,而只應該在發(fā)生嚴重問題的時候才用礁叔。大多數(shù)情況使用NSError是更好地選擇。
具體來說俗或,在手動管理引用計數(shù)的時候风罩,避免內存泄露的寫法是這樣的:

EOCSomeClass *object;
@try {
   object = [[EOCSomeClass alloc] init];
   [object doSomethingThatMayThrow];
}
@catch (…) {
   NSLog(@“error occurred”);
}
@finally {
   [object release];
}

關鍵在于要添加一個@finally塊,這是一個不管是否拋出異常都會到達的塊犀填,所以把release放在這里蠢壹,保證object的釋放。如果沒有這個塊九巡,把release放在@try里图贸,那么如果釋放前拋出了異常,釋放這一句就不會被調用冕广,內存泄露就會產生疏日。
如果在ARC環(huán)境,release就不能手動調用了撒汉。但需要注意的是沟优,和普通情況不同,此時系統(tǒng)默認情況下也不會自動幫我們調用睬辐,必須開啟-fobjc-arc-exceptions編譯器標志以后挠阁,ARC才可以生成這種情況下的附加代碼。但是會一定程度影響運行效率溯饵。
<br />


Item 33: Use Weak References to Avoid Retain Cycles

<br />
這一節(jié)講用弱引用打破保留環(huán)侵俗。
篇幅比較短,內容我也比較熟悉丰刊,好像沒有什么特別要記下來的坡慌。實際中最常見的場景就是用block的時候要小心,什么時候需要定義weakSelf藻三。如果block直接對self引用比較容易看出來洪橘,但是環(huán)里有兩個以上的對象的時候就不是很容易看出來跪者,比如block里引用了一個已經引用self的對象。
__unsafe_unretained和__weak都能有打破環(huán)的效果熄求,因為都并不保留對象渣玲,但是因為存在野指針的問題,__weak是更推薦的做法弟晚,更安全忘衍。
<br />


Item 34: User Autorelease Pool Blocks to Reduce High-Memory Waterline

<br />
這一節(jié)講通過新建autorelease pool來壓低內存的峰值。
“The high-memory waterline refers to the highest memory footprint of an application during a certain period.” 一開始不太懂這個waterline到底指的什么卿城,根據這句理解是程序運行中的內存峰值枚钓。
如果對對象調用autorelease而不是release,就會使對象多存活一段時間瑟押,到下一個event loop才會調用一次release搀捷,這里是指只是用系統(tǒng)自帶的那個寫在main函數(shù)的自動釋放池的情況。但是如果所有的對象都等到這時再釋放多望,內存就會一直積累嫩舟,峰值就會很高。為了避免這種情況怀偷,當出現(xiàn)占用內存多但是又可以用完就釋放的對象時家厌,可以手動創(chuàng)建一個自動釋放池來使它提前釋放,比如這樣:

NSArray *databaseRecords = /*…*/
NSMutableArray *people = [NSMutableArray new];
for (NSDictionary *record in databaseRecords) {
    @autoreleasepool {
       EOCPerson *person = [[EOCPerson alloc] initWithRecord:record];
       [people addObject:person];
    }
}

這個場景假設的是需要新建的person對象非常多椎工。如果不采用自動釋放池饭于,這些新建的person對象就會一直存在到下一個event loop,而采用這種寫法以后维蒙,在這個自動釋放池的末尾這些臨時對象就可以被回收了掰吕,這樣內存峰值就及時降下來了。
<br />


Item 35: Use Zombies to Help Debug Memory-Management Problems

<br />
這一節(jié)講的是用Zombie Objects來調試程序木西。
這個東西我不太熟悉畴栖,也沒有見過随静。不過原理還是比較好理解八千。對象在被釋放以后,原來存放對象的那塊內存會被標記為“可重用”燎猛,這樣就可以重新被分配做他用了恋捆。但是這個過程不是立即執(zhí)行的,具體什么時候執(zhí)行并不能確定重绷。所以這塊內存可能仍有東西在占用沸停,如果給它發(fā)消息有時甚至還能相應,但是不一定是我們希望的那個對象的響應昭卓,這樣就會有奇怪的Bug出現(xiàn)愤钾。而比較理想的情況是瘟滨,一旦內存被釋放了,不管有沒有被重新用掉能颁,我們都能得知這一信息杂瘸,如果給它發(fā)消息,能提示我們是在給已經釋放的對象發(fā)消息伙菊,利于我們調試败玉。
Zombie Object就能實現(xiàn)這一功能。默認是不打開NSZombieEnabled環(huán)境變量的镜硕,怎么打開文中寫了运翼,我找了一下,真的有誒←_←兴枯。

僵尸對象的原理是血淌,在NSObject執(zhí)行dealloc時,如果發(fā)現(xiàn)打開了NSZombieEnabled環(huán)境變量念恍,就通過method swizzling(Item13有講過)把dealloc的代碼變了六剥,多加了一部分,不僅把對象所屬的類變成NSZombie了峰伙,而且還自動加上了原類名作為后綴疗疟,就像_NSZombie_OriginalClassName這種形式。此時如果再向這個對象發(fā)送消息瞳氓,程序會判斷消息的接收者的類型策彤,如果是以NSZombie為前綴,就不會執(zhí)行這個消息匣摘,而是打印一條錯誤的信息出來店诗,提示“message sent to deallocated instance”,并且會顯示對象銷毀前的類名音榜。
使用Zombie Object是不會把內存釋放的庞瘸,只是把需要釋放的內存改了所屬類。但是只是在調試時會使用赠叼,所以不會引起實際的效率問題擦囊。
<br />


Item 36: Avoid Using retainCount

<br />
用了整整一節(jié)來嫌棄retainCount這個方法...
結論就是永遠都不要用。原因的話嘴办,其實這個方法的reference已經寫的比較明白了:

This method is of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

總的來說瞬场,就是因為引用計數(shù)是一個非常動態(tài)的過程,特別是有自動釋放池存在的情況下涧郊,計數(shù)的增減有實際意義贯被,而絕對值并沒有實際意義。不過文中給了更為詳細例子。比如有時系統(tǒng)會做優(yōu)化彤灶,對象在引用計數(shù)為1時就可能被回收看幼。再比如,單例對象的引用計數(shù)永遠都很大而且不變幌陕。再比如桌吃,某個調用方法內部可能自行保留或者釋放了對象,而外面看不出來苞轿,使得到的結果和想象得不一致茅诱。所以調用這個方法得不到任何有效的信息,結論就是搬卒,永遠不要用瑟俭。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市契邀,隨后出現(xiàn)的幾起案子摆寄,更是在濱河造成了極大的恐慌,老刑警劉巖坯门,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件微饥,死亡現(xiàn)場離奇詭異,居然都是意外死亡古戴,警方通過查閱死者的電腦和手機欠橘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來现恼,“玉大人肃续,你說我怎么就攤上這事〔媾郏” “怎么了始锚?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長喳逛。 經常有香客問我瞧捌,道長,這世上最難降的妖魔是什么润文? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任姐呐,我火速辦了婚禮,結果婚禮上转唉,老公的妹妹穿的比我還像新娘皮钠。我一直安慰自己稳捆,他們只是感情好赠法,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般砖织。 火紅的嫁衣襯著肌膚如雪款侵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天侧纯,我揣著相機與錄音新锈,去河邊找鬼。 笑死眶熬,一個胖子當著我的面吹牛妹笆,可吹牛的內容都是我干的。 我是一名探鬼主播娜氏,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼拳缠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了贸弥?” 一聲冷哼從身側響起窟坐,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绵疲,沒想到半個月后哲鸳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡盔憨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年徙菠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片郁岩。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡懒豹,死狀恐怖,靈堂內的尸體忽然破棺而出驯用,到底是詐尸還是另有隱情脸秽,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布蝴乔,位于F島的核電站记餐,受9級特大地震影響,放射性物質發(fā)生泄漏薇正。R本人自食惡果不足惜片酝,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望挖腰。 院中可真熱鬧雕沿,春花似錦、人聲如沸猴仑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至疾渣,卻和暖如春篡诽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背榴捡。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工杈女, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吊圾。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓达椰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親项乒。 傳聞我的和親對象是個殘疾皇子砰碴,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內容