《Objective-C高級編程》自動引用計數 閱讀筆記 item1(內存管理/引用計數)

《Objective-C高級編程》自動引用計數 閱讀筆記系列

《Objective-C高級編程》自動引用計數 閱讀筆記 item1(內存管理/引用計數)
《Objective-C高級編程》自動引用計數 閱讀筆記 item2(ARC規則及其實現)

前言

放假前從圖書館借了幾本技術書,Objective-C高級編程是其中的一本,在豆瓣里評價挺高的,有8.2。雖然現在iOS的絕大多數項目基本上都是ARC的了,但是深入了解下蘋果的引用計數式內存管理的思考方式總是好的。認真地看完了第一章自動引用計數,像這種深入底層、源代碼講解知識點的方式很棒,但是這排版真的很糟糕,經常得對一個知識點看個好幾遍才弄懂在講什么。另外,中文博大精深,要是在閱讀的過程中,遇到長句時,如果沒正確斷好語句,可能句子的意思會千差萬別(ps:古時候,文言文似乎是沒有句號等符號的,感謝發明符號的人,要不然現在的中文更難理解千萬倍)。本著把書讀薄的精神,試著做了下閱讀筆記,大多數都是摘抄自書籍。

1.1 自動引用計數(ARC,Automatic Reference Counting)

概念:指內存管理中對引用采取自動計數的技術。
關鍵點:在LLVM編譯器中設置ARC為有效狀態,就無需再次鍵入retain或者是release代碼。

1.2 內存管理/引用計數

1.2.1 通過辦公室照明形象地解釋內存管理,

Snip20160126_3.png

表1 對辦公室照明設備所做的動作和對Objective-C的對象所做的動作

對辦公室照明設備所做的動作 對Objective-C的對象所做的動作
開燈 生成對象
需要照明 持有對象
不需要照明 釋放對象
關燈 廢棄對象

由此,可以推出引用計數的內存管理

Snip20160126_4.png

1.2.2 內存管理的思考方式

  • 自己生成的對象,自己所持有
  • 非自己生成的對象,自己也能持有
  • 不再需要自己持有的對象時釋放
  • 非自己持有的對象無法釋放

表2 對象操作與Objective-C方法的對應

對象操作 Objective-C方法
生成并持有對象 alloc/new/copy/mutableCopy等方法
持有對象 retain方法
釋放對象 release方法
廢棄對象 dealloc方法

有關Objective-C內存管理的方法并不包含在Objective-C語言中,而是在包含在Cocoa框架中。如下:

Snip20160126_5.png

*** 自己生成的對象,自己所持有 ***
使用以下名稱開頭的方法意味著自己生成的對象只有自己持有:

  • alloc
  • new
  • copy
  • mutableCopy

注意:下列幾個方法,并不是同一類別的方法:

  • allocate
  • newer
  • copying
  • mutableCopyed

*** 非自己生成的對象,自己也能持有 ***
用alloc/new/copy/mutableCoy以外的方法取得對象,因為非自己生成并持有,所以自己不是該對象的持有者。但是通過retain方法,非自己生成的對象跟用alloc/new/copy/mutableCoy方法生成并持有的對象一樣,成為了自己所持有的。

*** 不再需要自己持有的對象時釋放 ***

  • 自己持有的對象,一旦不再需要,持有者有義務釋放該對象,務必使用release方法釋放。
  • 使用autorelease方法,可以使取得的對象存在,但自己不持有對象
  • 用來取得誰都不持有的對象的方法名不能以alloc/new/copy/mutableCopy開頭
  • 通過retain方法也能將調用autorelease方法取得的對象變為自己持有

注意:autorelease的功能

Snip20160126_6.png

*** 非自己持有的對象無法釋放 ***
釋放非自己持有的對象會造成程序崩潰。
相關案例:

  • 自己生成并持有對象后,在釋放完不再需要的對象之后再次釋放
  • 在“取得的對象存在,但自己不持有對象”時釋放

1.2.3 alloc/retain/release/dealloc實現

借助開源軟件GNUstep的源代碼中alloc/retain/release/dealloc的實現來理解蘋果的Cocoa實現。
總結如下:

  • 在Objective-C的對象中存在引用計數這一整數值
  • 調用alloc或是retain方法后,引用計數值加1
  • 調用release方法后,引用計數值減1
  • 引用計數值為0時,調用dealloc方法廢棄對象

1.2.4 蘋果的實現

由于NSObject類的源代碼沒有公開,利用Xcode的調試器(lldb)和iOS大概追溯內存管理和引用計數的實現。
蘋果的實現大概就是采用散列表(引用計數表)來管理引用計數。
如圖:

Snip20160126_7.png

GNUstep將引用計數保存在對象占用內存塊頭部的變量中,而蘋果的實現,則是保存在引用計數表的記錄中。
通過內存卡頭部管理引用計數的好處如下:

  • 少量代碼即可完成
  • 能夠統一管理引用計數用內存塊與對象用內存塊

通過引用計數表管理引用計數的好處如下:

  • 對象用內存塊的分配無需考慮內存塊頭部
  • 引用計數表各記錄中存有內存塊地址,可從各個記錄中追溯到各對象的內存塊

*** 關于蘋果的實現的第2條特性在調試時有著舉足輕重的作用:***

  • 即使出現故障導致對象占用的內存塊損壞,但只要引用計數表沒有被破壞,就能夠確認各內存塊的位置,如下:


    Snip20160126_8.png
  • 在利用工具檢測內存泄露時,引用計數表的各記錄也有助于檢測各對象的持有者是否存在

1.2.5 autorelease

autorelease的作用:

當超出對象實例的作用域(相當于變量作用域)時,對象實例的release實例方法被調用。

autorelease的具體使用方法如下:

  1. 生成并持有NSAutoreleasePool對象
  2. 調用已分配對象的autorelease實例方法
  3. 廢棄NSAutoreleasePool對象
Snip20160126_10.png

關鍵知識點:

  • 在大量產生autorelease的對象時,只要不廢棄NSAutoreleasePool對象,那么生成的對象就不能被釋放,因此有時產生內存不足的現象。例如,讀入大量圖像的同時改變其尺寸。在這類情況下,有必要在適當的地方生成、持有或廢棄NSAutoreleasePool對象。
Snip20160126_11.png
  • Cocoa框架中有很多類方法用于返回autorelease的對象。例如NSMutableArray類的arrayWithCapacity類方法

1.2.6 autorelease的實現

為了理解autorelease的實現,同樣需要查看GNUstep的源代碼。

關鍵知識點:

  • autorelease實例方法的本質就是調用NSAutoreleasePool對象的addObject類方法
  • addObject類方法調用正在使用的NSAutoreleasePool對象的addObject實例方法
  • 如果嵌套生成或持有的NSAutoreleasePool對象,理所當然會使用最內側的對象
  • 如果調用NSObject類的autorelease實例方法,該對象將被追加到正在使用的NSAutoreleasePool對象中的數組中
  • drain實例方法在廢棄autorelease對象數組之前,會先對數組中的所有對象調用release實例方法

1.2.7 蘋果的實現

通過objc4庫的runtime/objc-arr.mm可以確認蘋果的實現。

關鍵方法:

  • void *objc_autoreleasePoolPush(void){}
  • void objc_autoreleasePoolPop(void *ctxt){}
  • void *objc_autorelease(id obj){}

另外,通過NSAutoreleasePool類中的調用用非公開類方法showPools(該類方法只能在iOS中使用)來確認已被autorelease的對象的狀況。調試輸出用非公開函數_objc_autoreleasePoolPrint()。該函數在檢查某對象是否被自動release時非常有用。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容