我想弄清楚这段代码中的内存泄漏在哪里?
- (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,我在这里出错了吗?
请帮忙。
谢谢
答案 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];
}
}