2013-05-28 70 views
1

据我了解,如果启用ARC@autoreleasepool{}内的对象应该在不再使用时释放。目标C - autoreleasepool和ARC泄漏内存

但是,代码

#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{}作品。要解决这个问题,我应该在for循环中放置@autoreleasepool{}

+2

此代码分配大量内存,但不泄漏。 – stosha

+0

如果你知道这是一个泄漏,为什么做这样一个大循环来证明如此而不是一次迭代? :) –

+1

我其实认为这是一个很好的例子。我不知道为什么它获得了如此多的赞誉。 –

回答

3

要了解如何自动释放的作品,比较下面你原来此代码:

for (int i = 0; i < 1000000000; i++) 
{ 
    @autoreleasepool 
    { 
     NSString* string = @"ab c"; 
     NSArray* array = [string componentsSeparatedByString:string]; 
    } 
} 

自动释放对象被标记为释放,当他们走出去的范围,但实际上没有未公布直到autorelease部分的末端(这是autorelease池被排空的地方)。因此,上面的代码将在循环中每次释放标记的对象,而您的原始代码只会在循环结束时释放它们。

自动释放池可以嵌套,当对象被自动释放时,可以使用最近的池。这允许你从[NSString stringWithFormat:@"%d", i];这样的函数返回对象 - 返回的字符串的保留计数为1,但被标记为自动释放 - 你可以暂时使用它,但是如果你需要保留它以备后用,你需要保留它(当您将其分配给强大的参考时会发生这种情况)。所以当你保留它时,保留计数会变为2,然后当它自动释放时,保留计数将变为1,并且都是好的。如果你永远不会保留它,那么当自动释放时,保留计数将变为0并且对象被处理。

3

你的理解是错误的

  1. 这不会有任何与ARC
  2. 这不是垃圾收集,所以对象不会释放时他们停止使用
  3. 自动释放池释放对象当它被排空([NSAutoreleasePool drain])或被摧毁。你没有明确地分配池,所以它只会在return之前被排空一次。
+0

如果你试图分配10亿个这样的对象,就算GC也会有一个conniption – CodaFi

+0

@CodaFi好吧,GC可以在每次迭代后轻松地释放对象。然而,更大的问题是可能阻止其他线程正常工作的“几乎无限”循环。这真的取决于GC的实施。 – Sulthan

+0

OS X垃圾收集器运行在一个低优先级的后台线程IIRC上,所以我想知道在这种情况下如何“停止这个世界”(但它可能只是在循环中拥塞) – CodaFi

3

在我的理解,如果启用ARC,里面@autoreleasepool对象{}应该当他们不再使用的释放。

好的,退后一步,实际考虑一下。对于每一次内存泄漏,ARC并不是一种神奇的捕获方式,它仍然是手动保留释放,只是编译器插入手动保留释放。 @autoreleasepool {}在给出“内存泄漏”的例子时并不排除谨慎的需要,也没有赋予您分配10亿个对象并将其称为框架错误的权利。事实证明,你所做的可能会超负荷交给你的autorelease池,并且你要么等待足够长的时间才能正常终止循环,要么你被操作系统杀死了(我敢打赌后者比前者更多)。自己运行这个程序后,我可以确认给定的自动释放池确实耗尽了分配的RAM的速度,这只需要很长时间。

如果去掉循环,甚至缩短其持续时间(100,甚至1000就足够了),你可以看到,但绝对没有对象的泄漏,而这一切都是正确的去恐龙的方式:

enter image description here

+0

非常好的答案。 – Mike