Reputation: 79
I am trying to figure out where is memory leaked in this piece of code ?
- (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] gives 2 before [item release] and [list autorelease] will make the reference count 0, am i going something wrong here ?
Please help.
Thank you
Upvotes: 0
Views: 176
Reputation: 32681
Dont rely on retainCount
. The system or the internal code of the classes can retain your object internally and release it later, that's their business and you can't know, so you don't really know what value to expect in retainCount
. That's not the good way to search for leaks
At multiple times in your code, you allocate an object (in your case an NSString
), then ignore it to override the variable with some other value:
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
Thats quite like if you were doing:
int i = 5;
i = 12;
Of course the first value is useless and not needed. But in the case of your code, this value that you never uses allocate memory that is never reclaimed so it leaks.
party
variable, you later send a release
to this new object. But party
contains an autoreleased object already, as you affected [result stringForColumn:xxx]
to it, and according to code naming conventions, this method returns an autoreleased object. So you do not need to send a release
on this new object.So your loop should simply look like the following instead:
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];
}
}
Upvotes: 0
Reputation: 15228
NSString *type = [[NSString alloc] init];
type = [result stringForColumn:@"legislative_type"];
You are creating an NSString 'type' which has a retain count of one, but then assign a different object to it. Remove the first line and just use this:
NSString *type = [result stringForColumn:@"legislative_type"];
You also need to remove the [type release]
since stringForColumn
returns an autoreleased NSString (at least if it adheres to the Cocoa naming conventions).
Upvotes: 1