我有一个程序,它读取一个巨大的文本文件(逐行),并在将该行写入数据库之前对每行执行一些字符串操作。
程序需要越来越多的内存,所以我想我可能需要释放我使用的字符串。但它没有帮助。所以我把以下代码放在一起来测试实际发生的情况。经过一些反复试验,我发现当我在自动释放池上进行排水时,它可以正常工作。
我想知道我做了什么。所以我问:
这是我的测试程序
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int cnt = 0;
while (cnt < 1000000000) {
NSMutableString *teststr = [[NSMutableString alloc] init];
teststr = [NSString stringWithString:@"Dummy string just for the demo"];
cnt++;
if (cnt % 1000000 == 0) {
printf("cnt=%i\n",cnt);
}
[teststr release];
// [pool drain]; // It works when I do this
// [[NSAutoreleasePool alloc] init]; // and this
}
[pool drain];
return 0;
}
编辑:基于到目前为止的答案,我查看了我的原始程序并更改了测试程序:
//teststr = [NSString stringWithString:@"Dummy string just for the demo"];
[teststr appendString:@"Dummy string just for the demo"];
这是否也会创建一个新字符串?因为我还有记忆问题。我的例程工作方式是我用字符串附加一些东西,但可能在开头用一个空字符串开头。
答案 0 :(得分:2)
NSMutableString *teststr = [[NSMutableString alloc] init];
这会分配一个可变字符串....
teststr = [NSString stringWithString:@"Dummy string just for the demo"];
然后此使用自动释放的字符串覆盖 teststr
变量。已分配的可变字符串现在无法访问,但仍保留+1,因此它将被泄露。
[teststr release];
这只会释放自动释放的字符串,以后会导致双重自由错误。
如果您需要手动管理的可变字符串,则应使用
NSMutableString* teststr = [[NSMutableString alloc] initWithString:@"Dummy string just for the demo"];
...
[teststr release];
并且在发布或转让所有权之前不要直接分配给teststr
。
答案 1 :(得分:1)
你犯了一个非常基本的错误。
方法stringWithString
返回一个新的自动释放字符串,因此无法分配/初始化它。此外,因为它是自动释放的对象,所以耗尽自动释放池会有所帮助。
所以而不是:
NSMutableString *teststr = [[NSMutableString alloc] init];
teststr = [NSString stringWithString:@"Dummy string just for the demo"];
试试这个:
NSMutableString *teststr = [NSString stringWithString:@"Dummy string just for the demo"];
答案 2 :(得分:0)
以上示例并没有真正存在太多内存问题。我的更复杂的程序“泄露”内存,这是因为以下声明消耗了内存而没有消耗。
NSString *conv = [dict objectForKey:astring]];
这不是真正的泄漏,但是有几种类型的陈述和数十万次的迭代引起了一个大问题。解决方案是排出自动释放池。但是,耗尽自动释放池的缺点是我使用的字典对象(字典)也被耗尽了。
所以这就处理了。我打开了第二个游泳池:
NSAutoreleasePool * pool2 = [[NSAutoreleasePool alloc] init];
NSString *conv = [dict objectForKey:astring]];
/* do something */
[pool2 drain];