代码之家  ›  专栏  ›  技术社区  ›  hol

目标C内存泄漏理解问题

  •  0
  • hol  · 技术社区  · 14 年前

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

    程序需要越来越多的内存,所以我想可能需要释放我使用的字符串。但没有帮助。所以我把下面的代码放在一起测试实际发生了什么。通过一些尝试和错误,我发现当我对自动释放池进行消耗时,它是有效的。

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

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

    这是我的测试程序

    #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 回复  |  直到 14 年前
        1
  •  2
  •   Eiko    14 年前
    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];
    

    不要分配给 塞斯特罗 直接,在它被释放或所有权被转移之前。

        2
  •  1
  •   Hemant    14 年前

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

    1. 调用alloc/init时必须释放对象。
    2. 如果使用其他方法(方便的构造函数、方法的返回对象等)获取对象,则会自动释放对象。

    方法 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"];
    
        3
  •  0
  •   hol    14 年前

    上面的例子并没有出现太多的内存问题。我更复杂的程序“泄漏”内存,这是因为下面的语句耗尽了内存而没有消耗。

    NSString *conv = [dict objectForKey:astring]];
    

    这并不是一个真正的漏洞,但是这种声明和几十万次迭代造成了一个大问题。解决方案是排出自动释放池。但是排出自动释放池的缺点是我使用的字典对象(dict)也被排出了。

    所以这就解决了。我开了第二个游泳池:

    NSAutoreleasePool * pool2 = [[NSAutoreleasePool alloc] init];
    
    NSString *conv = [dict objectForKey:astring]];
    
    /* do something */
    
    [pool2 drain];