我有一个奇怪的(在我看来)和简单的内存泄漏情况使用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。顺便说一句,它不是作为仪器中的内存泄漏事件捕获的,但我认为的情况是明显的内存泄漏。
答案 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
的结尾处。控制台应用程序。