2013-05-28 36 views
1

據我瞭解,如果啓用ARC@autoreleasepool{}內的對象應該在不再使用時釋放。目標C - autoreleasepool和ARC泄漏內存

但是,代碼

#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     for (int i = 0; i < 1000000000; i++) { 
      NSString *string = @"ab c"; 
      NSArray *array = [string componentsSeparatedByString:string]; 
     } 
    } 
    return 0; 
} 

泄漏存儲器。

儀器顯示,泄漏的對象是__NSArrayM創造的 - [的NSString componentsSeparatedByString:]

所以,問題是:爲什麼__NSArrayM對象在創建它們的相同的循環迭代不被破壞?

誰能幫我解決這個問題

更新:謝謝你的答案,看來我使用的術語「內存泄漏」不當和誤解如何@autoreleasepool{}作品。要解決這個問題,我應該在for循環中放置@autoreleasepool{}

+2

此代碼分配大量內存,但不泄漏。 – stosha

+0

如果你知道這是一個泄漏,爲什麼做這樣一個大循環來證明如此而不是一次迭代? :) –

+1

我其實認爲這是一個很好的例子。我不知道爲什麼它獲得瞭如此多的讚譽。 –

回答

3

要了解如何自動釋放的作品,比較下面你原來此代碼:

for (int i = 0; i < 1000000000; i++) 
{ 
    @autoreleasepool 
    { 
     NSString* string = @"ab c"; 
     NSArray* array = [string componentsSeparatedByString:string]; 
    } 
} 

自動釋放對象被標記爲釋放,當他們走出去的範圍,但實際上沒有未公佈直到autorelease部分的末端(這是autorelease池被排空的地方)。因此,上面的代碼將在循環中每次釋放標記的對象,而您的原始代碼只會在循環結束時釋放它們。

自動釋放池可以嵌套,當對象被自動釋放時,可以使用最近的池。這允許你從[NSString stringWithFormat:@"%d", i];這樣的函數返回對象 - 返回的字符串的保留計數爲1,但被標記爲自動釋放 - 你可以暫時使用它,但是如果你需要保留它以備後用,你需要保留它(當您將其分配給強大的參考時會發生這種情況)。所以當你保留它時,保留計數會變爲2,然後當它自動釋放時,保留計數將變爲1,並且都是好的。如果你永遠不會保留它,那麼當自動釋放時,保留計數將變爲0並且對象被處理。

3

你的理解是錯誤的

  1. 這不會有任何與ARC
  2. 這不是垃圾收集,所以對象不會釋放時他們停止使用
  3. 自動釋放池釋放對象當它被排空([NSAutoreleasePool drain])或被摧毀。你沒有明確地分配池,所以它只會在return之前被排空一次。
+0

如果你試圖分配10億個這樣的對象,就算GC也會有一個conniption – CodaFi

+0

@CodaFi好吧,GC可以在每次迭代後輕鬆地釋放對象。然而,更大的問題是可能阻止其他線程正常工作的「幾乎無限」循環。這真的取決於GC的實施。 – Sulthan

+0

OS X垃圾收集器運行在一個低優先級的後臺線程IIRC上,所以我想知道在這種情況下如何「停止這個世界」(但它可能只是在循環中擁塞) – CodaFi

3

在我的理解,如果啓用ARC,裏面@autoreleasepool對象{}應該當他們不再使用的釋放。

好的,退後一步,實際考慮一下。對於每一次內存泄漏,ARC並不是一種神奇的捕獲方式,它仍然是手動保留釋放,只是編譯器插入手動保留釋放。 @autoreleasepool {}在給出「內存泄漏」的例子時並不排除謹慎的需要,也沒有賦予您分配10億個對象並將其稱爲框架錯誤的權利。事實證明,你所做的可能會超負荷交給你的autorelease池,並且你要麼等待足夠長的時間才能正常終止循環,要麼你被操作系統殺死了(我敢打賭後者比前者更多)。自己運行這個程序後,我可以確認給定的自動釋放池確實耗盡了分配的RAM的速度,這隻需要很長時間。

如果去掉循環,甚至縮短其持續時間(100,甚至1000就足夠了),你可以看到,但絕對沒有對象的泄漏,而這一切都是正確的去恐龍的方式:

enter image description here

+0

非常好的答案。 – Mike