NSAutoreleasePool自动释放池如何工作?

时间:2020-03-05 18:54:11  来源:igfitidea点击:

据我了解,使用alloc,new或者copy创建的任何内容都需要手动释放。例如:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

我的问题是,这样难道不是同样有效吗?:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}

解决方案

回答

是的,第二个代码段是完全有效的。

每次将-autorelease发送给对象时,都会将其添加到最内部的autorelease池中。当池耗尽时,它仅向池中的所有对象发送-release。

自动释放池只是一种便利,它使我们可以将发送-release推迟到"以后"。这种"后期"可能会在多个地方发生,但是在Cocoa GUI应用程序中最常见的是当前运行循环周期的结尾。

回答

是的,没有。我们最终将释放字符串内存,但是如果在垃圾回收(不是内存托管)环境下运行NSAutoreleasePool对象,则使用排水而不是释放将NSAutoreleasePool对象"泄漏"到内存中。这种"泄漏"只会使NSAutoreleasePool的实例像其他任何在GC下没有强指针的对象一样"不可访问",并且该对象将在下一次GC运行时被清除,这很可能直接在调用-drain之后`:

drain
  
  In a garbage collected environment, triggers garbage collection if memory allocated since last collection is greater than the current threshold; otherwise behaves as release.
  ...
  In a garbage-collected environment, this method ultimately calls objc_collect_if_needed.

否则,它类似于在非GC下-release的行为,是的。正如其他人所说,-release在GC下是禁止操作的,因此确保池在GC下正常运行的唯一方法是通过-drain,而在非GC下的-drain的工作方式与非GC下的-release,并且可以说也更清楚地传达了其功能。

我应该指出,语句"用new,alloc或者init调用的任何内容"都不应包含" init"(但应包含" copy"),因为" init"不会分配内存,它只会设置对象(构造函数)时尚)。如果收到分配对象,并且函数仅这样调用init,则不会释放该对象:

- (void)func:(NSObject*)allocd_but_not_init
{
    [allocd_but_not_init init];
}

那不会消耗比我们开始时更多的内存(假设init不会实例化对象,但是无论如何我们都不会对这些对象负责)。

回答

不你错了。该文档明确指出,在非GC环境下,-drain等效于-release,这意味着NSAutoreleasePool将不会泄漏。

回答

NSAutoreleasePool:消耗与释放

由于drainrelease的功能似乎引起混乱,因此在这里可能需要澄清(尽管在文档中已对此进行了介绍)。

严格来说,从全局角度来看," drain"不等同于" release":

在参考计数的环境中,drain'确实执行与release'相同的操作,因此,两者在这个意义上是等效的。要强调的是,这意味着如果我们使用drain而不是release,则不会泄漏池。

在垃圾收集的环境中,release是禁止操作的。因此,它没有任何作用。另一方面," drain"包含了一个向收集器的提示,即它应该"根据需要收集"。因此,在垃圾收集的环境中,使用" drain"有助于系统平衡收集扫描。

回答

是的,代码是完美的,如果我们要使用垃圾收集,只需在完成处理后将字符串设置为nil就足够了。垃圾收集不利于应用程序的性能,因此我不建议我们使用它:P

回答

我发现此链接提供了有关何时以及如何使用NSAutoReleasePool的最佳解释:AutoReleasePool