1

我排干了一个自动释放池。警告*** attempt to pop an unknown autorelease pool意味着自动释放池是用不同的方法创建和排出的——这很好。

但这是否意味着这样的水池没有被耗尽?有解决办法吗?

4

1 回答 1

5

@itaiferber 不正确,他链接到的开发博客文章也是如此。

NSAutoreleasePools不是在 Stack 上创建的。它们被分配在堆上,就像所有其他 Cocoa 对象一样。

我认为混乱的根源在于它在文档中说:

每个线程(包括主线程)维护自己的 NSAutoreleasePool 对象堆栈(参见“线程”)。随着新池的创建,它们被添加到堆栈的顶部。当池被释放时,它们会从堆栈中删除。

文档中提到的“栈”不是调用栈,而是栈数据结构。这意味着如果你有“自动释放池1”,然后创建第二个自动释放池,然后自动释放一个对象,当第二个自动释放池耗尽时,该对象将被释放。

总而言之:只要您了解这样做的内存含义,完全欢迎您以一种方法创建自动释放池并在另一种方法中将其耗尽。(这是否是糟糕的设计完全是另一个问题)

如果你最终没有排空池,当父自动释放池被排空时,它将为你排空。

如果你释放了一个不是栈顶的自动释放池,这会导致栈上所有(未释放的)自动释放池连同它们的所有对象一起被释放。如果您在完成后忽略将释放发送到自动释放池(不建议这样做),则它会在它嵌套的自动释放池之一被释放时被释放。

因此,如果您的自动释放池堆栈如下所示:

 _____
|  1  |  <--- most recently allocated pool
|-----|
|  2  |
|-----|
|  3  |  <--- least recently allocated pool
 -----

然后你排空池 3,池 2 和 1 也会自动排空。我猜这就是你的代码中发生的事情。您正在创建“池 1”,然后当“池 3”被排空时它会自动排空,然后您尝试自己排空池 1,但它不再有效,并且您“试图弹出一个未知数自动释放池”。

如果您尝试在 GUI 应用程序中挂起自动释放池,则此问题尤其明显。在这样的应用程序(基于 UIKit 或 AppKit)中,运行循环将在循环的每次通过时创建和销毁一个自动释放池,这意味着您在循环迭代期间创建的任何自动释放池将在下一次循环时被销毁大约。

有关这方面的更多具体信息,内存管理编程指南的整个部分都专门介绍了自动释放池。

于 2010-08-14T21:30:47.923 回答