返回参数对象时,ARC内存泄漏

时间:2012-05-26 15:35:24

标签: objective-c ios automatic-ref-counting instruments

我有一个奇怪的(在我看来)和简单的内存泄漏情况使用ARC(自动引用计数)。我正在使用iOS代码,但我认为它应该适用于Objective-C。


我有一个跟随函数,它在检查参数对象的属性后返回指定为参数的对象。

- (id) returnParam:(id) obj
{
    // Do whatever filtering needed. Return nil for invalid input.

    return (NSNumber *)obj;
}

如果我在循环中调用此方法如下,我可以看到分配的内存不断增加,直到循环在Instruments中结束。

for(int i = 0; i < 1000000; i++)
{        
    id obj = [[NSNumber alloc] initWithInt:i];        
    id obj2 = [self returnParam:obj];
    NSLog(@"attempt %@", obj2);
}


但是,如果我将returnParam函数的内容放在循环中,如下所示,一切正常。内存脚印章的长度保持不变。

for(int i = 0; i < 1000000; i++)
{        
    id obj = [[NSNumber alloc] initWithInt:i];

    // Do whatever filtering needed. Break on invalid input.

    id obj2 = obj;

    NSLog(@"attempt %@", obj2);
}


我已经删除了过滤部分(基本上该函数只将对象传递给调用者),同样的情况仍然存在。


不理解为什么这个序列没有减少保留计数的假设,我在这里和那里尝试了所有可能的__weak__unsafe_unretained组合,但都没有效果。

有人可以解释为什么这个(返回参数对象)不起作用,并建议我解决这个问题?


P.S。顺便说一句,它不是作为仪器中的内存泄漏事件捕获的,但我认为的情况是明显的内存泄漏。

1 个答案:

答案 0 :(得分:3)

这不是泄漏。它与-autorelease的工作方式有关。扩展-returnParam:的作用:

-(id) returnParam:(id) paramToReturn
{
   // make sure the variable is in the scope for the entirety of the function
   id returnValue = nil;
   @try 
   {
       // when the parameter is passed in, ARC will automatically retain it.
       [paramToReturn retain];
       returnValue = [paramToReturn retain]; // strong assignment (a = b)
       return returnValue;
   }
   @finally
   {
       [paramToReturn release]; // release the value we retained when we passed in the parameter
       [returnValue autorelease]; // autorelease the return value so it is still valid after the function exits.
   }
}

现在,让我们将其与您的其他循环进行比较:

for (int i = 0; i < 1000; i++)
{
    id obj = [[NSNumber numberWithInt:i] retain]; // retain, because 'obj' is strong by default.
    id obj2 = [obj retain]; // retain, because 'obj2' is strong by default

    NSLog(@"attempt %@", obj2);

    [obj release]; // release because 'obj' is strong
    [obj2 release]; // release because 'obj2' is strong.
}

因此,在弹出下一个autorelasepool之前,您的变量不会被清理,这通常发生在iPhone应用程序的下一个NSRunLoop刻度线上,或者可能发生在@autoreleasepool的结尾处。控制台应用程序。