【问题标题】:Autorelease Pool Blocks自动释放池块
【发布时间】:2013-04-16 06:51:26
【问题描述】:

我最近在阅读Advanced Memory Management 文档时偶然发现了自动释放池块。文档指出:

您可以在循环中使用自动释放池块在下一次迭代之前处理这些对象。在循环中使用自动释放池块有助于减少应用程序的最大内存占用。[...] 在自动释放池块内发送自动释放消息的任何对象都会在块结束时释放。

在块内创建的没有自动释放调用的对象怎么办?我假设他们也将保留计数减为 0。然后,我的问题是,无论哪种方式,在块内创建的对象都会在块结束时获得释放调用,调用 autorelease 有什么意义?

【问题讨论】:

    标签: ios memory-management autorelease


    【解决方案1】:

    可以通过发送-release-autorelease 消息来释放对象。

    使用-release,引用计数会立即减少,这可能会导致释放。

    使用-autorelease 时,递减会延迟以使对象在其创建范围之外保持活动状态。例如,辅助方法-createFoo 可能会返回一个自动释放的对象,以便调用者可以使用返回的对象,而无需在从方法返回时立即释放它,也不必担心谁负责释放它。

    使用 ARC,编译器会为您处理所有这些细节。您需要知道的是,有时使用autorelease 可以使对象保持活动的时间更长。

    这种“保持活动”行为对以下循环有影响:

    - (void)foobar
    {
        for (/* a long time */) {
            NSMutableString *s = [NSMutableString string];
            // ...
        }
    }
    

    NSMutableString 上的 +string 方法将返回一个自动释放的对象。这不会在循环迭代或方法结束时自动释放(嗯,ARC 可以通过查看调用堆栈进行一些巧妙的优化,但我们将忽略这一点)。这意味着当您在循环体内时,您将获得无限的内存增长。

    请注意,如果我们使用了以下内容:

    NSMutableString *s = [[NSMutableString alloc] init];
    

    然后 ARC 将在循环体的末尾插入一个 release 调用,并且该字符串将立即被释放。

    要解决第一个示例的无限内存增长问题,您需要定义一个显式自动释放池:

    - (void)foobar
    {
        for (/* a long time */) {
            @autoreleasepool {
                NSMutableString *s = [NSMutableString string];
                // ...
            }
        }
    }
    

    现在,在循环的每次迭代之后,自动释放池都会被销毁,并且在池内自动释放的所有对象(包括我们的字符串)都将立即释放。

    所以这完全取决于您调用的方法类型以及它们是否返回自动释放的对象。

    【讨论】:

    • “现在,在循环的每次迭代之后,自动释放池都会被销毁,并且在池中自动释放的任何对象(包括我们的字符串)都将立即释放。”那么如果它们没有在内部自动释放呢?无论如何,它们不会在自动释放块结束时被释放,因为它们的寿命不能超出该块吗?然后我的问题仍然存在:当对象在块末尾释放时,为什么我们需要自动释放调用?
    • 自动释放池只释放自动释放的对象。对于非自动释放对象,编译器将在适当的位置插入显式释放调用,以便在自动释放池结束之前释放它们。
    • 以防万一你误会了:在我帖子的第一个代码块中,没有自动释放池。当方法返回时,在方法或循环内创建的任何自动释放对象都不会被释放。它们将在稍后发布。在大多数 UI 代码中,都会为 runloop 的每次迭代创建一个更高级别的自动释放池。但是如果你有一个紧密的循环,你必须创建你自己的以避免创建太多的对象。
    • 好吧,你的意思是,在 ARC 之前,如果你在自动释放池中创建了一个对象并且你没有在块的末尾释放它,那么该对象将继续存在于自动释放池的块范围?
    • @Theo。这与ARC没有任何关系。总是有自动释放池并且行为方式完全相同。
    猜你喜欢
    • 2013-04-18
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2011-08-04
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多