2011-11-17 53 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池被释放。