【问题标题】:Autorelease pools in Objective-C - release main AutoreleasePool?Objective-C 中的自动释放池 - 释放主 AutoreleasePool?
【发布时间】:2012-01-22 21:32:14
【问题描述】:

据我了解,当向对象发送autorelease 消息时,如果除main.m 中的自动释放池之外不存在自动释放池,则该对象将被放置在main.m 中的自动释放池中。假设这是正确的,我有几个问题:

1) 所有自动释放的对象是否都保留在该池中,直到应用程序终止?

2) 如果 1 为真,在没有本地自动释放池的情况下创建自动释放对象(因此将该对象放入 main.m 池中)是否会将该对象保留在内存中,直到应用程序终止或收到内存警告?

3) main.m 自动释放池何时耗尽,除了应用收到内存警告或应用终止时?

例如,在像这样的 cellForRowAtIndexPath 委托方法中:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Foobar"];
if (cell == nil) {
    // No cell to reuse => create a new one
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Foobar"] autorelease];

    // lots of custom stuff
}

return cell;

细胞何时真正释放?它们必须自动释放,因为您不能在返回它们之前释放它们,并且您不能在之后释放它们,因为它们超出了范围。根据我目前的理解,细胞被放置在最顶层的自动释放池中,并在该池耗尽/释放时释放。在这种情况下,这将是应用程序中唯一的自动释放池; main 中的那个。

4) 问题在于,即使我完成了这些单元格并且视图控制器已被释放,这些单元格仍保留在内存中,是吗?如果不是这种情况,有人可以解释这种情况下的内存管理是如何工作的吗?谢谢!

注意:我查看了 Apple 的文档,但它主要讨论了何时使用您自己的本地自动释放池,而不是关于它们的实际功能。

【问题讨论】:

    标签: objective-c ios memory-management autorelease nsautoreleasepool


    【解决方案1】:

    来自documentation

    Application Kit 在事件循环的每个循环开始时在主线程上创建一个自动释放池,并在结束时将其排出,从而释放在处理事件时生成的所有自动释放对象。如果您使用 Application Kit,则通常不必创建自己的池。但是,如果您的应用程序在事件循环中创建了大量临时自动释放对象,则创建“本地”自动释放池以帮助最大限度地减少峰值内存占用可能会有所帮助。

    因此,默认池中的自动释放对象只会在当前事件的持续时间内存活。

    【讨论】:

      【解决方案2】:

      1) 是否所有自动释放的对象都保留在该池中,直到应用程序终止?

      根据定义,自动释放对象归其自动释放池所有,直到该池被耗尽。当您向对象发送-autorelease 时,该对象将添加到池稍后将释放的对象列表中。自动释放池组织在一个堆栈中,堆栈顶部的池是添加任何发送-autorelease 的对象的池。在main() 中创建的池通常不是堆栈顶部的池。例如,运行循环会在每次迭代开始时创建一个自动释放池。

      2) 如果 1 为真,是否创建一个没有本地的自动释放对象 自动释放池(因此将该对象放在 main.m 池中) 将该对象保留在内存中,直到应用程序或内存终止 收到警告了吗?

      如果在main() 中创建的池是最顶层的池,则会出现这种情况,但如上所述,通常情况并非如此。

      3) main.m 自动释放池何时耗尽,除了当 应用收到内存警告或应用被终止?

      main() 中创建的池与任何其他自动释放池之间没有区别。当池被释放时,它们都被耗尽,或者如果你使用@autorelease 指令,它们会在块的末尾被耗尽。

      【讨论】:

      • 嗯...我错了。关于很多东西!感谢您提供一些启示
      • “根据定义,自动释放的对象由它们的自动释放池保留”这是不正确的。自动释放池不保留任何内容。自动释放只不过是一种延迟消息机制。当您向对象发送 -autorelease 时,它​​不会增加其保留计数。它将对象添加到对象列表中,当自动释放池本身被释放或发送 -drain 消息时,将发送 -release 消息。
      • 另外几点:(1) 自动释放池是每个线程的,因此,自动释放的对象永远不能安全地在两个线程之间传递。 (3)顶层水池很可能永远不会被耗尽,因为没有意义;如果一个应用程序被终止,它会发出最终的“我要离开这里”通知,然后直接退出()而不用费心耗尽池。
      • @NSResponder 你是对的——选词不当。也许“拥有”是一个更好的词,因为自动释放池基本上承担了释放自动释放对象的责任。
      • 不,“拥有”也不是一个好的选择。 Cocoa 和 Cocoa touch 的新手经常感到困惑,并且认为自动释放池在概念上类似于堆。也许苹果应该称它们为“Autoreleaser”之类的东西,并把“pool”这个词去掉。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多