Retain Count

| 11/23/2011
Retain Counting 是 Cocoa 程式設計不可不學的一個記憶體管理機制。一個好的程式員,在對系統記憶體運用以及管理上面做的要是不佳,就很容易出現效能、漏洞、程式崩潰等問題。

所有的 Objective-C 物件都必須要由指標來建立。一般我們很習慣在 C 語言裡面,使用 malloc 產生一塊可以讓指標所指向的「值」。在物件導向設計裡面,我們簡單的稱這個「值」叫做「實體」(instance)。蘋果在設計 Cocoa 的基礎物件 NSObject 裡面,設計了一個簡單的物件方法 (Object Method): +(id)alloc,可以讓產生一個鄉對應物件所需要的一塊實體的記憶體空間,並且回傳實體的指標。當實體被成功建立之後,我們必須要使用 NSObject 實體方法 (Instance Method) 的 -(id)init 來初始化它。這一條基本規則建立起 Retain Counting 所需具備的一切條件。所有繼承 NSObject 的子孫物件都必須要遵守這一條規則。

OWNObject *val;
// call object method    [object_name method_name]
val = [OWNObject alloc];
// call instance method  [var_name method_name]
val = [val init];

Retain Counting 的機制很簡單,物件建立之後,所有繼承 NSObject 的物件都會有一個 retainCount 的 變數 (ivar) 這個變數會在方法 -(id)init 的時候變成 1,-(void)retain 的時候增加, -(void) release 的時候減少。當這個數值變成 0 的時候,物件會自動呼叫 -(void)dealloc,並且將記憶體釋放出來。


// retain count = 1
val = [val init];
// retain count = 2
[val retain]
// retain count = 1
[val release]
// retain count = 0
[val release] -> call [self dealloc] automatically


!記住,千萬不可以自己去呼叫 -(void)dealloc,程式會崩潰!

講到這裡,會有很多人覺得這個跟 Java 的 Reference Counting 的機制不是一樣嗎?其實是不同的。在這裡,記憶體的分配、釋放都是由物件:也就是應用程式本身來執行,而 Java 的 Reference Counting 則是由 Garbage Collocation Daemon 一段時間去掃描所有在記憶體中的物件,找出 Reference Count = 0 的實體並且釋放。這裡雖然遺留了 C 語言在動態記憶體分配之後,程式設計師必須要自己管控記憶體的工作,也有些現代程式語言的精巧。

雖然說蘋果在最新的 LLVM Compiler 3.0 裡面,新增了 Auto Retain Count 的機制,可以讓編譯器幫助你決定在程式碼的哪一個部位 retain、release。但是自動化機制總是會犧牲掉一般程式設計師可以掌握的彈性。我認為理解清楚這個機制,可以有助益於任何記憶體管理方面的進步!


0 意見: