2011-11-17 57 views
2

這個循環是存在內存泄漏:NSMutableArray的環路出現內存泄漏,甚至當我明確地釋放它

int64_t i,verylongnumber; 

//misc. code 

for(i=0;i<verylongnumber;i++){ 
    NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects: 
      [NSNumber numberWithLongLong:65535], 
      [NSNumber numberWithLongLong:65535], 
      [NSNumber numberWithLongLong:65535], 
      [NSNumber numberWithLongLong:65535], 
      nil]; 
    [myArray removeAllObjects]; 
    [myArray release]; 
} 

我已經竭盡所能,以保持它的內存泄露,但我不能。我認爲這與NSNumbers有關。我假設它們是自動發佈的,但這是否意味着我必須單獨釋放它們(即使用alloc)?我怎麼會這樣做呢?爲每個NSNumber創建一個單獨的變量並將其插入到數組中?這似乎很多工作。我試過[myArray removeAllObjects],但這沒有什麼區別。它在我自己的線程中擁有自己的autorelease池。我不確定這是否有所作爲。

這個固定:

我增加了一個額外的自動釋放池,內環路:

int64_t i,verylongnumber; 

//misc. code 

for(i=0;i<verylongnumber;i++){ 

    NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init]; 

    NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects: 
      [NSNumber numberWithLongLong:65535], 
      [NSNumber numberWithLongLong:65535], 
      [NSNumber numberWithLongLong:65535], 
      [NSNumber numberWithLongLong:65535], 
      nil]; 
    [myArray release]; 

    [pool2 drain]; 
} 
+0

你可能想看看進入'@ autoreleasepool'聲明,這既是ARC和MRC支持下,比NSAutoreleasePool更快(在ARC轉換少了一個步驟,當你到這一點)。 –

回答

6

我將在此拍攝刺..

您可以刪除[myArray的removeAllObjects],因爲它是多餘的。 NSArray的確保留他們的對象,但是當數組本身被釋放時,他們也釋放它們。

本身自動釋放的NSNumbers。但是,如果你做了一個非常大的循環,那麼這個自動釋放的內存不會被釋放,直到for循環退出並最終運行循環(除非你在某處設置了一個單獨的NSAutoreleasePool)。

所以我可以看到內存的使用情況如何隨着這個循環迭代,但在完成它應該釋放內存。你是如何得出你有泄漏的結論的?

+0

謝謝。我只是在循環中添加了另一個autorelease池,似乎​​解決了這個問題。 – Synthetix

+0

我很高興工作。如果你對我的回答滿意,如果你接受了,我會很感激。 – Carter

3

你等着看,如果對象獲得的近期釋放?

自動釋放對象在不久的將來的某個時候發佈。在上面的例子中,創建許多對象的循環次數很多。他們不會在該代碼的範圍內發佈。

在GUI應用程序這意味着當運行迴路正在運行該函數返回之後。在控制檯應用程序中,這是遊戲池發佈的時間。

退房:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

自動釋放池提供了一種機制,使您可以發送對象的 「延遲」釋放消息。

的關鍵是遞延點。

編輯:(後評論)

注意,您可以排水池。另一種選擇是創建非自動發佈的數字(alloc/init),並在長時間運行的循環中顯式釋放。取決於代碼,這可能是可取的,因爲排空池可能會釋放延遲釋放的對象,稍後該循環/作用域假定的代碼仍然是延遲的。如果你想控制它,然後控制它。

+0

它們需要在每次循環迭代時釋放,因爲循環將運行很長時間。隨着時間的推移,即使少量的內存也會隨着應用內存使用量的增加而增加。 – Synthetix

+0

好的 - 正如自動發佈池文檔所指出的那樣,您可以將其耗盡。你的其他選擇是創建(分配,初始化,複製)數字,然後明確釋放它們。這樣可以明確控制你想在該循環中釋放的內容(可以是gui),而不會疏忽地推遲發佈的其他項目。 – bryanmac

1

當NSArray添加到NSArray時,NSArray會保留對象。這意味着NSArray擁有該對象的所有權。當從NSArray或NSArray中刪除對象時,該對象被釋放(引用計數-1)。如果對象沒有任何其他所有者,則對象被銷燬。
下面的代碼將創建內存泄露

NSNumber *number = [[NSNumber alloc]initWithFloat:floatValue]; //reference count is 1, you are the owner 
[aArray addObject:number] //reference count is 2, aArray is also owner. 

所以刪除內存泄漏,你建議立即進行刪除版本號。

NSNumber *number = [[NSNumber alloc]initWithFloat:floatValue]; //reference count is 1, you are the owner 
[aArray addObject:number] //reference count is 2, aArray is also owner. 
[number release]; // reference count is 1, you are not owner og number  

如果您將autorelease對象添加到NSArray,則不需要釋放該對象。當autorelease池彈出時,該對象將失去其所有權。
在你的每個for循環的例子中,NSNumber被創建,而舊的仍然在內存中等待autorelease池被釋放。