NS自动释放池
我耗尽了自动释放池。警告***尝试弹出未知的自动释放池
意味着自动释放池是通过不同的方法创建和耗尽的 - 这很好。
但这是否意味着这样的池没有被排空? 有解决办法吗?
I drained an autorelease pool. The warning *** attempt to pop an unknown autorelease pool
means the autorelease pool was created and drained in different methods - that's fine.
But does it mean such pool is NOT being drained?
Is there a solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
@itaiferber 是不正确的,他链接到的开发博客文章也是如此。
NSAutoreleasePools不是在堆栈上创建的。就像所有其他 Cocoa 对象一样,它们在堆上分配。
我认为混乱的来源是在文档中它说:
文档中提到的“堆栈”不是调用堆栈,而是一个堆栈数据结构。这意味着,如果您有“自动释放池1”,然后创建第二个自动释放池,然后自动释放一个对象,则当第二个自动释放池耗尽时,该对象将被释放。
总之:我们非常欢迎您在一种方法中创建自动释放池并在另一种方法中耗尽它,只要您了解这样做对内存的影响。 (这是否是一个糟糕的设计完全是另一个问题)
如果您最终没有耗尽池,那么当父自动释放池被耗尽时它将为您耗尽。
因此,如果您的自动释放池堆栈如下所示:
然后您排空池 3,池 2 和 1 也将自动排空。我猜这就是您的代码中发生的情况。您正在创建“池 1”,然后当“池 3”耗尽时它会自动耗尽,然后您尝试自己耗尽池 1,但它不再有效,并且您“尝试弹出一个未知的”自动释放池”。
如果您尝试在 GUI 应用程序中保留自动释放池,这个问题尤其明显。在此类应用程序(基于 UIKit 或 AppKit)中,运行循环将在每次循环时创建和销毁自动释放池,这意味着您在循环迭代期间创建的任何自动释放池都将在下一次循环出现时销毁大约。
有关这方面的更多具体信息,请参阅 内存管理编程指南的整个部分专门介绍自动释放池。
@itaiferber is incorrect, as is the Dev Blog post he links to.
NSAutoreleasePools are not created on the Stack. They are allocated on the heap, just like all other Cocoa objects.
I think where the confusion comes from is that in the documentation it says:
The "stack" referred to in the documentation is not the call stack, but a stack data structure. This means that if you have "autorelease pool 1", and then create a second autorelease pool, and then autorelease an object, the object will be released when the second autorelease pool is drained.
In summary: you are perfectly welcome to create an autorelease pool in one method and drain it in another, as long as you understand the memory implications of doing so. (Whether or not this is bad design is another question entirely)
If you end up not draining the pool, it will be drained for you when a parent autorelease pool is drained.
So if your autorelease pool stack looks like:
And you then drain pool 3, pools 2 and 1 will automatically be drained as well. I'm guessing this is what's happening in your code. You're creating "pool 1", and then it's getting automatically drained when "pool 3" gets drained, and then you're attempting to drain pool 1 yourself, but it's no longer valid, and you are "attempting to pop an unknown autorelease pool".
This problem because especially apparent if you're trying to hang on to autorelease pools in a GUI application. In such applications (UIKit or AppKit based), the run loop will create and destroy an autorelease pool on every pass of the loop, which means that any autorelease pool you create during an iteration of the loop will be destroyed the next time the loop comes around.
For much more specific information on this, there's an entire section of the Memory Management Programming Guide devoted to autorelease pools.