我无法理解@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。
答案 0 :(得分:0)
正在创建临时内存,并由代码中的代码和它调用的API调用自动释放。在池耗尽之前,不会释放此内存。耗尽的通常点是在运行循环中。但是你的循环不允许运行循环执行,所以通过将@autoreleasepool放在循环中,池可以在代码运行时耗尽。