我正在尝试从磁盘读取文件,将其分开,将其存储到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;
答案 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;它可以工作,它会处理字符串和字符集的问题。