据我了解,任何用 分配, 新的, , 或者 复制 需要手动释放。例如:

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 被发送到一个对象时,它都会被添加到最里面的自动释放池中。当池被耗尽时,它只是向池中的所有对象发送 -release 。

自动释放池只是一种方便,允许您将发送 -release 推迟到“稍后”。“稍后”可能发生在多个地方,但在 Cocoa GUI 应用程序中最常见的是在当前运行循环周期的末尾。

其他提示

NS自动释放池:排水对比发布

由于函数 drainrelease 似乎引起了混乱,这里可能值得澄清(尽管这在 文档...).

严格来说,从大局来看 drain不是 相当于 release:

在引用计数环境中, drain 执行与以下相同的操作 release, ,所以两者在这个意义上是等价的。强调一下,这意味着你做 不是 如果你使用的话会导致水池泄漏 drain 而不是 release.

在垃圾收集的环境中, release 是一个空操作。因此它没有效果。 drain, 另一方面,包含对收集器的提示,即它应该“在需要时收集”。因此,在垃圾收集环境中,使用 drain 帮助系统平衡收集清理。

正如已经指出的,您的第二个代码片段是正确的。

我想建议一种更简洁的方法来使用适用于所有环境(引用计数、GC、ARC)的自动释放池,并且还可以避免耗尽/释放混淆:

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

在上面的示例中,请注意 @autoreleasepool 堵塞。这是有记录的 这里.

不你错了。文档明确指出,在非GC下,-drain相当于-release,意味着NSAutoreleasePool将 不是 被泄露。

我从苹果公司读到的内容:“在自动释放池块的末尾,块内接收到自动释放消息的对象将被发送一条释放消息——每次在块内发送自动释放消息时,对象都会收到一条释放消息。”

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

向对象发送 autorelease 而不是 release 可以延长该对象的生命周期,至少直到池本身耗尽为止(如果随后保留该对象,则可能会更长)。一个对象可以多次放入同一个池中,在这种情况下,每次将其放入池中时,它都会收到一条释放消息。

是和不是。如果您在垃圾收集(非内存管理)环境下运行它,您最终会释放字符串内存,但通过使用排出而不是释放将 NSAutoreleasePool 对象“泄漏”到内存中。这种“泄漏”只是使 NSAutoreleasePool 的实例像 GC 下任何其他没有强指针的对象一样“无法访问”,并且该对象将在下次 GC 运行时被清理,这很可能是在调用 -drain:

流走

在垃圾收集环境中,如果自上次收集以来分配的内存大于当前阈值,则触发垃圾收集;否则表现为释放。...在垃圾收集环境中,该方法最终调用 objc_collect_if_needed.

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

我应该指出,你的陈述“任何用 new、alloc 或 init 调用的东西”不应该包含“init”(但应该包含“copy”),因为“init”不分配内存,它只设置对象(构造函数时尚)。如果您收到一个分配的对象,并且您的函数仅调用 init ,则不会释放它:

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

这不会消耗比您已经开始使用的更多的内存(假设 init 不实例化对象,但您无论如何也不对这些负责)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top