Objective-C循环遍历数组会占用大量内存

时间:2013-01-23 18:12:29

标签: objective-c memory-management

我正在尝试从磁盘读取文件,将其分开,将其存储到NSArray中,然后遍历该数组并对数据执行一些非常基本的操作。但是,如果我使用的是小文件(大约5000行数据,每行一个字),我最终会在循环结束时使用几百兆字节的内存。如果我使用的是非常大的文件(约200,000行),我最终会使用几千兆字节的内存!为什么会这样?当我将文件加载到数组中时,我应该看到内存的初始峰值,但是内存使用应该保持相当稳定。我当时正在使用ARC,但我不相信它,所以现在我自己做了所有的内存管理,我确信我已经发布了我在循环中分配的所有临时内容。

NSString *fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

NSScanner *scanner = [NSScanner scannerWithString:fileContents];
NSMutableArray *wordList = [[[NSMutableArray alloc] init] autorelease];
while (![scanner isAtEnd]) {
    NSString *line = [[NSString alloc] init];
    [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&line];
    [wordList addObject:line];
    [line release];
}
return wordList;

1 个答案:

答案 0 :(得分:4)

我看到两个问题;你不成功创建一个字符串,你应该从循环中提升字符集的创建。扫描仪也可能创建临时对象;你还应该在循环中添加一个内部自动释放池。

NSMutableArray *wordList = [[[NSMutableArray alloc] init] autorelease];
NSCharacterSet * newline = [NSCharacterSet newlineCharacterSet];
while (![scanner isAtEnd]) {
    @autoreleasepool{
        NSString *line;
        [scanner scanUpToCharactersFromSet:newline intoString:&line];
        [wordList addObject:line];
    }
}

字符串只是一个普通的旧泄漏; scanUpToCharactersFromSet:intoString:不会要求分配字符串,并且您之后丢失了对它的引用 - release并未定位与您分配的实例相同的实例。然而,理查德是对的,这里分配的内存量不是太大。

至于字符集,自动释放池在循环期间没有耗尽,所以如果newlineCharacterSet正在创建并在每次调用时自动释放一个新实例,那么你将在那里建立内存太。我希望NSCharacterSet足够聪明,可以为您缓存它,但String Programming Guide中的注释:

  
      
  • 缓存字符集(可能是在全局字典中),而不是不断地重新创建它们。
  •   

表明可能并非如此。

然而,我的三个建议中最有效的一个可能是内部自动释放池。

最后,使用ARC;它可以工作,它会处理字符串和字符集的问题。

相关问题