2011-06-30 15 views
9

我一直在iPhone上編程很長一段時間,並且對內存管理有不好的經驗。我想知道下面的方式是不是釋放內存的好方法。這是釋放內存的好方法嗎?

int count = [someObject retainCount]; 

for (int i = 0; i < count; i ++) 
{ 
[someObject release]; 
} 

本方法絕望在少數情況下(特別是UIWebViews)我曾面臨的行爲。變量的retainCount減少到零,這將釋放它正在使用的內存。該方法有點髒,但是有沒有與之相關的瓶頸?

+5

不,這不是釋放內存的好方法。 – Sneakyness

+0

請儘快閱讀Apple的內存管理文檔,其中解釋瞭如何管理內存。永遠不要這樣做。 – 2011-06-30 17:15:51

回答

28

你不應該依靠retainCount因爲有通過iOS框架保留對象的可能性,

閱讀下面什麼蘋果說的retainCount

重要提示:此方法通常的 沒有價值在調試內存 管理問題。由於框架對象的任何數量的 可能保留 對象,以保持引用 它,而在同一時間 自動釋放池可持有 對象的任何 推遲發行的數量,這是非常不可能的,你 可以從這個 方法中獲得有用的信息。

要理解必須遵守的內存管理基本規則,請閱讀「Memory Management Rules」。要診斷內存管理的問題,使用合適的工具:

+3

更不用說,*你自己的一個對象*也是保留對象的可能性。它的對象無關緊要;如果在某些事物仍然堅持的情況下將對象捅死,您將在稍後導致崩潰。 –

3

您不應該依賴retainCount的值。您應該儘可能經常撥打alloccopy

編輯:和newretain

+0

並'保留'也。 – beryllium

+0

和'new'也:) – beryllium

+4

NARC ...新的alloc保留副本 –

14

此代碼是絕對不用去。它只是隱藏了你的編程錯誤 - 而且它是以非常糟糕的方式進行的。

請了解正確的內存管理。沒有替代品。

這是memory management programming guide。這是值得閱讀不止一次。

+1

這個。這個千次! –

7

正如其他人所提到的,-retainCount實際上是無用的。當您不熟悉Objective-C中的內存管理/引用計數時,嘗試使用 - retainCount來幫助理解引用計數的工作原理有時很誘人,但實際上,它最多可能(看起來)令人困惑。

您發佈的代碼本身具有潛在的危險性,具體取決於您的周圍環境如何使用someObject。將它應用於其他你並不期望的情況也會很危險。以使用@"a string"編譯器指令創建的恆定NSString:這些字符串被創建並設計爲永遠不會被釋放。因此應用代碼就像下面這個例子會導致一個無限循環:

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    NSString *string = @"theString"; 

    NSLog(@"retainCount == %lu", (unsigned long)[string retainCount]); 

    for (NSUInteger i = 0; i < [string retainCount]; i++) { 
     [string release]; 
    } 

    [pool drain]; 
    return 0; 
} 

此打印:

2011-06-30 08:40:16.287 retainCount[35505:a0f] retainCount == 1152921504606846975

,然後進入一個無限循環。

+0

哦,我沒有想過靜態和單身 - 很好的答案! – deanWombourne

+0

我不會釋放一個常數。我知道這個版本只需要爲新的,分配,複製和保留而被調用。只是在少數情況下,一些物體保留的數量超出了我的預期。我發佈的方法只是針對這幾個案例的一項工作。但從發佈的答案,我想最好找出爲什麼它被保留,而不是使用該方法:)。 –

+2

當談到保留計數時,「超出我的預期」並不意味着「不正確」。這也不一定意味着你需要做任何事情來降低它 - 只要確保你自己的責任得到了照顧,你自己的新/分配/保留/複製呼叫都與相應的(自動)版本保持平衡,並且一切都會好起來。對於除您以外的物體,請記住 - NSVegas中會發生什麼,停留在NSVegas中。 :-) –

6

我不能說不夠強調!

把你的代碼的這個例子在行動:

// Create an autoreleased object 
MyObject *myObject = [[[MyObject alloc] init] autorelease]; 

// Run your code to make it dealloc itself 
int count = [myObject retainCount]; 
for (int i = 0; i < count; i ++) 
    [myObject release]; 

您的代碼將迫使myObject被dealloced。

但是,myObject也已放入自動釋放池 - 一旦池開始釋放它的對象,您的應用就會崩潰,因爲myObject不再存在!

規則很簡單:每次使用init,new或copy時調用release。否則,這不是你的問題。

+0

關於這個答案的最好的一點是,你描述了一個問題,不是即使你的示例代碼有問題。這就是爲什麼您應該依賴引用計數規則(或自動引用計數或垃圾回收)而不是試圖對框架進行二次猜測的原因。 – 2011-06-30 15:00:38

+0

我很困惑 - 對stringWithString的調用會將myString添加到autorelease池中 - 然後這會在未來某個時候嘗試釋放它。我錯過了什麼?(雖然很清楚,但我絕對不是說這是OP代碼的唯一問題,這僅僅是一個例子) – deanWombourne

+0

'+ stringWithString:/ *一個NSConstantString * /'的實例將返回常量字符串,所以你實際上試圖釋放一個靜態對象。正如我所說,重要的部分是它是錯誤的:試圖聰明地認爲它的錯誤只會以眼淚而告終。 – 2011-06-30 15:53:37

相關問題