使用仪器检测内存泄漏

时间:2012-10-03 16:35:45

标签: iphone memory-leaks

我想弄清楚这段代码中的内存泄漏在哪里?

- (NSMutableArray *) fetchAidDetails:(NSNumber *) rowID {
    NSMutableArray *list = [[NSMutableArray alloc] init];    
    FMDatabase *db = [[FMDatabase databaseWithPath:[self dbPath]] retain];
    if(![db open]) {
        [db release];        
        return [list autorelease];
    }

    NSString *query = [NSString stringWithFormat:@"select legislative_type, legislative_name from legislative_aid where official_id = %d", rowID.unsignedIntValue];

    FMResultSet *result = [[db executeQueryWithFormat:query] retain];

    while ([result next]) {
        NSMutableDictionary *item = [[NSMutableDictionary alloc] init];        
        NSString *type = [[NSString alloc] init];
        type = [result stringForColumn:@"legislative_type"];
        [item setObject:type forKey:@"legislative_type"];
        [type release];

        NSString *party = [[NSString alloc] init];
        party = [result stringForColumn:@"legislative_name"];
        [item setObject:party forKey:@"legislative_name"];
        [party release];

        [list addObject:item];
        [item release];
    }

    [result release];
    [db close];
    [db release];

    return [list autorelease];
}

[item retainCount]在[item release]之前给出2,[list autorelease]会使引用计数为0,我在这里出错了吗?

请帮忙。

谢谢

2 个答案:

答案 0 :(得分:1)

NSString *type = [[NSString alloc] init];
type = [result stringForColumn:@"legislative_type"];

您正在创建一个NSString“type”,其保留计数为1,但随后会为其指定一个不同的对象。删除第一行,然后使用:

NSString *type = [result stringForColumn:@"legislative_type"];

您还需要删除[type release],因为stringForColumn会返回一个自动释放的NSString(至少如果它符合Cocoa命名约定)。

答案 1 :(得分:0)

  • 不要依赖retainCount。系统或类的内部代码可以在内部保留您的对象并在以后释放它,这是他们的业务而您无法知道,因此您并不真正知道retainCount中期望的值。这不是搜索泄漏的好方法

  • 在代码中多次分配一个对象(在您的情况下为NSString),然后忽略它以使用其他值覆盖该变量:

    NSString *party = [[NSString alloc] init]; // You allocate memory for an NSString object
    party = [result stringForColumn:@"legislative_name"]; // then you completely forget about it and override your party variable with a different object
    

这就像你在做的那样:

int i = 5;
i = 12;

当然,第一个值是无用的,不需要。但就您的代码而言,您从未使用的这个值会分配永远不会回收的内存,因此会泄漏。

  • 然后在受影响的另一个对象转到party变量后,您稍后会向此新对象发送release。但是party已经包含了一个自动释放的对象,因为它影响了[result stringForColumn:xxx],并且根据代码命名约定,此方法返回一个自动释放的对象。因此,您无需在此新对象上发送release

所以你的循环应该只是如下所示:

while ([result next])
{
  @autoreleasepool {
    NSMutableDictionary *item = [[NSMutableDictionary alloc] init];        
    NSString *type = [result stringForColumn:@"legislative_type"];
    [item setObject:type forKey:@"legislative_type"];

    NSString *party = [result stringForColumn:@"legislative_name"];
    [item setObject:party forKey:@"legislative_name"];

    [list addObject:item];
    [item release];
  }
}