为什么@autoreleasepool的位置很重要?

时间:2015-06-22 11:55:32

标签: objective-c xcode memory-management automatic-ref-counting avfoundation

我无法理解@autoreleasepool是如何工作的。请考虑以下示例,其中我将为audiofile创建AVAssetReader。为了使记忆影响重要,我重复了这一步1000次。

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>

void memoryTest() {
    NSURL *url = [[NSURL alloc] initWithString:@"path-to-mp3-file"];
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil];
    AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:asset error:NULL];
}

int main(int argc, const char * argv[]) {

    // Breakpoint here (A)

    @autoreleasepool {
        for(int i = 0; i < 1000; i++) {
            memoryTest();
        }
    }

    // Breakpoint here (B)

    return 0;
}

在断点A和断点B的循环之前和之后,我在Xcode调试导航中查看了我的应用程序的内存使用情况。在A点,我的应用程序消耗大约1.5MB的内存。在B点,它大约是80MB。有趣的是,当我将自动释放池放入循环中时,B的内存使用量下降到大约4MB:

for(int i = 0; i < 1000; i++) {
    @autoreleasepool { memoryTest(); }
}

为什么这个位置很重要? (断点 - 在两种情况下 - 都在自动释放池之外!)在任何一种情况下,B点消耗的内存与循环次数成正比。我在这里错过了其他的东西以释放它的记忆吗?

我想到导航器中的内存图表会被延迟,但是在断点不改变任何内容之前添加usleep。如果我将memoryTest()更改为

void memoryTest() {
    NSURL *url = [NSURL URLWithString:@"path-to-mp3-file"];
}

@autoreleasepool的位置无关紧要。难道不是很奇怪吗?

我正在使用支持ARC的Xcode 6,OS X SDK 10.10。

1 个答案:

答案 0 :(得分:0)

正在创建临时内存,并由代码中的代码和它调用的API调用自动释放。在池耗尽之前,不会释放此内存。耗尽的通常点是在运行循环中。但是你的循环不允许运行循环执行,所以通过将@autoreleasepool放在循环中,池可以在代码运行时耗尽。