根据我的理解,如果ARC
已启用,则@autoreleasepool{}
内的对象应在不再使用时释放。
然而,代码
#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{}
的工作原理。要解决此问题,我应该将@autoreleasepool{}
放在for循环中。
答案 0 :(得分:3)
你的理解是错误的
[NSAutoreleasePool drain]
)或销毁时释放对象。你没有明确地排空游泳池,所以它只会在return
之前排空一次。答案 1 :(得分:3)
据我了解,如果启用了ARC,@ autoreleasepool {}内的对象应该在不再使用时释放。
好的,退后一步,实际上想一想。对于每次内存泄漏,ARC都不是一个神奇的解决方案,它仍然是手动保留释放,只是编译器插入手动保留释放。在给出“内存泄漏”的例子时,@autoreleasepool {}
并没有避免谨慎的需要,它也没有赋予你分配10亿个对象并将其称为框架bug的权利。事实证明,你所做的可能是重载了它给你的自动释放池,你要么没有等待足够长的时间让循环正常终止,要么你被操作系统杀死(我敢打赌)后者多于前者)。自己运行之后,我可以确认给定的自动释放池确实耗尽了这个分配的RAM的Gigs,它只需要很长时间。
如果你移除了循环,甚至缩短了它的持续时间(100,甚至1000就足够了),你可以看到绝对没有物体泄漏,并且一切都正确地影响了恐龙:
答案 2 :(得分:3)
要了解autorelease的工作原理,请将以下代码与原始代码进行比较:
for (int i = 0; i < 1000000000; i++)
{
@autoreleasepool
{
NSString* string = @"ab c";
NSArray* array = [string componentsSeparatedByString:string];
}
}
自动释放的对象在超出范围时会被标记为释放,但在自动释放部分结束之前(自动释放池耗尽)才会实际释放。因此,上面的代码每次都会在循环中释放标记的对象,而原始代码只会在循环结束时释放它们。
自动释放池可以嵌套,在自动释放对象时使用最接近的池。这允许您从[NSString stringWithFormat:@"%d", i];
等函数返回对象 - 返回的字符串的保留计数为1但标记为自动释放 - 您可以暂时使用它,但如果您需要保留它以供以后使用,则需要保留它(当你将它分配给强引用时会发生)。因此,当你保留它时,保留计数变为2,然后当它自动释放时,保留计数变为1并且一切都很好。如果你从未保留它,那么当自动释放时,保留计数变为0并且对象被解除分配。