1

我正在构建一个 iPhone 应用程序,我在其中分离一些线程以在后台执行长时间运行的工作,以免挂起 UI。我知道线程需要 NSAutoreleasePool 实例来进行内存管理。我不确定线程​​方法是否调用另一个方法 - 该方法是否还需要 NSAutoreleasePool?

示例代码:

- (void)primaryMethod {
    [self performSelectorInBackground:@selector(threadedMethod) withObject:nil];
}

- (void)threadedMethod {
    NSAutoreleasePool *aPool = [[NSAutoreleasePool alloc] init];

    // Some code here

    [self anotherMethod];

    // Maybe more code here

    [aPool drain];
}

- (void)anotherMethod {
    // More code here
}

我问的原因是我收到的错误是对象正在自动释放而没有适当的池,并且“只是泄漏”。

我已经看到人们根本没有自动释放池的其他问题,我理解为什么需要自动释放池。我特别想知道在(在本例中)创建的自动释放池是否threadedMethod适用于在anotherMethod.

4

3 回答 3

7

要回答您的问题,是的,anotherMethod 正在使用您在 threadedMethod 中创建的 NSAutoreleasePool,当 aPool 被释放/耗尽时,您自动释放的任何东西都会被释放。

因此,您的错误不太可能直接源于此代码(除非还有更多事情发生)。

在 _NSAutoreleaseNoPool 上放置一个断点(在 Breakpoints 窗口中按名称添加它)并在调试器中运行您的代码,它会在没有池的情况下调用 autorelease 时停止,这应该可以解决您的问题。

于 2009-06-18T05:13:47.373 回答
0

在您的示例中,是的, NSAutoreleasePool 跨方法进行,因为调用[self anotherMethod]嵌套在 -(void)threadedMethod中。

  • Q: NSAutoreleasePool 跨方法携带?
  • 答:这取决于:
    1. 跨嵌套调用,是的。
    2. 在兄弟调用中,没有。

无论如何,NSAutoreleasePool当父范围消失时,实例本身就会超出范围。- 在您的示例中,在-(void)threadedMethod { }.

前面提到的文章(http://thegothicparty.com/dev/macos/nsautoreleasepool/)对此非常清楚。

于 2010-05-12T05:42:34.550 回答
-1

自动释放池确实会传递给另一个方法。但是,当您的线程函数结束时,您应该调用 [aPool release] 而不是 [aPool drain]。它们大致相同,但 aPool 释放会导致 NSAutoreleasePool 释放自身以及池中的所有其他对象。当您的线程函数在调用 drain 后结束时,自动释放池的保留计数仍然为 +1!奇怪的是,“刚刚泄漏”的对象是 aPool!

编辑:

吉姆普尔斯关于释放和排水是等价的是正确的。Apple 文档明确表示它们在非垃圾收集环境中是相同的,并且在垃圾收集的情况下排水效果更好。不阅读文档是我的错!

这是一篇介绍 NSAutoreleasePools 的一般概述的文章 - 它应该可以帮助您指出正确的方向。由于有一个自动释放池的虚拟堆栈,因此最上面的一个将在您的应用程序中的任何地方使用 - 无论对象在哪里被自动释放。

http://thegothicparty.com/dev/macos/nsautoreleasepool/

于 2009-06-18T03:28:43.147 回答