2009-02-26 73 views
2

我有點通過以下行爲,我編爲iPhone模擬器(或設備)的Xcode項目中看到的困惑:Objective-C的內存問題(iPhone)

NSString *test = [[NSString alloc] initWithCString:"foo"]; 

NSLog(@"test retain count = %d", [test retainCount]); // prints 1 

[test release]; 

NSLog(@"test retain count = %d", [test retainCount]); // also prints 1 instead of 0 

然而,任何進一步嘗試訪問'測試'導致Xcode環境崩潰,無論是另一個[test retainCount] NSLog語句或其他(即使只檢查測試是否等於零)。

想法?在簡單的基於視圖的測試項目中編譯...代碼存在於項目的applicationDidFinishLaunching方法中。

澄清 - 我不知道在實踐中做到以上幾點。這只是一個測試,看看爲什麼在某些調試情況下,保留數爲1並不真實反映對象的真實狀態。感謝您的迴應。這只是一個測試存根,看看爲什麼我在幾個案例中看到某些行爲。我真正想要做的是追蹤一個非常小的內存泄漏(0.06MB),每當我銷燬/重新創建自定義視圖時,都會一直創建它。

回答

5

保留計數是一種調試幫助,可能會誤導Cocoa可能在後臺執行的操作。在數據永久可用並且從未真正刪除的字符串文字中尤其如此。

集中確保您的代碼遵循關於對象所有權的Cocoa memory management rules。必要時,使用儀器檢查實際的內存泄漏。

+0

那麼這正是我使用保留計數 - 作爲調試幫助。我正在平衡我的alloc調用等。我只是想進一步檢查事情,以幫助跟蹤我在類dealloc()方法中遇到的問題。 – 2009-02-26 21:03:28

+1

「保留計數是一種調試幫助」。不,他們是**不是**調試幫助。 – 2011-08-18 12:21:36

0

不要依賴保留計數...框架可能會保留自己的東西。

取而代之的是,依靠內存管理規則來實現objective-C。如果你分配,初始化或新的東西,你擁有它並負責釋放它。如果你沒有,你不是。

5

您在test後已被釋放,並可能重新分配的調用retainCount,所以肯定結果是不可靠的,更不要說你不應該發送交易對象的任何消息。

0

當您發送release時,該字符串被處理 - 它沒有其他所有者保留它。發送更多消息(包括retainCount)是一個錯誤,不會返回任何有意義的消息。

正如其他人所指出的,不要依賴保留計數特別有用。它們是您可以看到的一幅圖片,但它們往往會讓人誤解。例如,autoreleases不會顯示在保留計數中,有時對象會被保留額外的時間以用於緩存目的,等等。但是,在這種特殊情況下,您根本不會將消息發送給有效對象,幸運的是找回答案而不是崩潰。

如果您對此不清楚,您應該閱讀Apple's memory management guide。這對編程Cocoa來說不是太複雜,也是絕對必要的。

0

改進上面顯示的代碼的一個技巧是使用'set to nil'約定。

EG:

的NSString *測試= [[NSString的頁頭]方法initWithCString:爲 「foo」]; (@「test retain count =%d」,[test retainCount]); //打印1

[測試發佈]; test = nil; //設置爲零,因爲我已經釋放了指針,我不應該再使用它。 NSLog(@「test retain count =%d,test foobarpro =%d」,[test retainCount],[test foobarPro]); //現在打印0和0--因爲任何一個零對象上的objective-c調用返回0(並且不會崩潰)

通過在您釋放它之後將指針設置爲零,您將來可以驗證您的代碼:稍後有人出現並編輯下面10行代碼可能會意外地使用「測試」,可能沒有不良影響(或明顯的崩潰)。我甚至在dealloc調用中設置了nil指針,因爲在銷燬中使用非零「壞」指針時會發生一些最難的調試任務。

此外,您可以使用殭屍進行調試,以查找使用像無效測試這樣的指針的情況。

--Tom