Objective-C内存泄漏理解问题

时间:2010-10-02 10:43:10

标签: objective-c memory-management memory-leaks

我有一个程序,它读取一个巨大的文本文件(逐行),并在将该行写入数据库之前对每行执行一些字符串操作。

程序需要越来越多的内存,所以我想我可能需要释放我使用的字符串。但它没有帮助。所以我把以下代码放在一起来测试实际发生的情况。经过一些反复试验,我发现当我在自动释放池上进行排水时,它可以正常工作。

我想知道我做了什么。所以我问:

  • 为什么发布不释放内存?
  • 有更好的方法吗?

这是我的测试程序

#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"];

这是否也会创建一个新字符串?因为我还有记忆问题。我的例程工作方式是我用字符串附加一些东西,但可能在开头用一个空字符串开头。

3 个答案:

答案 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)

你犯了一个非常基本的错误。

  1. 当你调用alloc / init时,你必须释放一个对象。
  2. 如果使用其他方法(方便的构造函数,方法的返回对象等)获取对象,则会自动释放对象。
  3. 方法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];