Hi,
Instruments detected some leaks in my code but I don't understand where the problem is. To me everything seems to be release correctly but I'm just a beginner in Objective-C :-)
Maybe could someone help me to understand my mistakes here.
In table mode, the detail pane is indicating in the Leaked Object column my object Person (6 times for the length of my Instruments recording with each time the same stack trace)
Note : by the way I'm very astonished to see also a lot of Foundation, ImageIO, UIKit, CoreGraphics objects mentioned as leaked objects in the detail pane.
Can it be that Apple's frameworks are full of leaks !!!!
The extended detail pane is showing a stack indicating that the leak seems to happen when calling -[Person setPartnersWithPrimaryKey:andPreviousPartner:datab ase:]
If I go down in the detail pane to the code, it's showing me :
Code:
- (void)setPartnersWithPrimaryKey:(NSInteger)pk andPreviousPartner:(Person*) thePreviousPartner database:(sqlite3 *)db {
const char *partnersSql = "SELECT person_id FROM person, relation_list_list, relation, partner_list_list WHERE person.relation_list_id = relation_list_list.relation_list_id AND relation_list_list.relation_id = relation.relation_pk AND relation.partner_list_id = partner_list_list.partner_list_id AND pk = ? AND person_id <> ?";
if (partners_statement != nil) {
sqlite3_finalize(partners_statement);
partners_statement = nil;
}
if (sqlite3_prepare_v2(database, partnersSql, -1, &partners_statement, NULL) != SQLITE_OK)
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
sqlite3_bind_int(partners_statement, 1, pk);
sqlite3_bind_int(partners_statement, 2, pk);
NSMutableArray *aPartnersArray = [[NSMutableArray alloc] init];
while (sqlite3_step(partners_statement) == SQLITE_ROW) {
int partner_id = sqlite3_column_int(partners_statement, 0);
Person *aPartner;
if (partner_id == thePreviousPartner.primaryKey) {
aPartner = thePreviousPartner;
} else {
aPartner = [[Person alloc] initWithPrimaryKey:partner_id database:db];
}
[aPartnersArray addObject:aPartner];
[aPartner release];
}
self.partners = aPartnersArray;
[aPartnersArray release];
}
with 3 highlighted lines in this code which are :
1) NSMutableArray *aPartnersArray = [[NSMutableArray alloc] init];
2) aPartner = [[Person alloc] initWithPrimaryKey

artner_id database:db];
3) [aPartnersArray addObject:aPartner];
To me aParnersArray and aPartner are released in this code.
So, where is the problem ? Where is the leak ?
For completeness, here is the code of initWithPrimaryKey
Code:
- (id)initWithPrimaryKey:(NSInteger)pk database:(sqlite3 *)db {
if (self = [super init]) {
primaryKey = pk;
database = db;
if (init_statement != nil) {
sqlite3_finalize(init_statement);
init_statement = nil;
}
// Compile the query for retrieving person data. See insertNewBookIntoDatabase: for more detail.
// Note the '?' at the end of the query. This is a parameter which can be replaced by a bound variable.
// This is a great way to optimize because frequently used queries can be compiled once, then with each
// use new variable values can be bound to placeholders.
const char *sql = "SELECT firstname,lastname, picture, birthdate, lastdate, father_id, mother_id, sex, me FROM person WHERE pk=?";
if (sqlite3_prepare_v2(database, sql, -1, &init_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
// For this query, we bind the primary key to the first (and only) placeholder in the statement.
// Note that the parameters are numbered from 1, not from 0.
sqlite3_bind_int(init_statement, 1, primaryKey);
if (sqlite3_step(init_statement) == SQLITE_ROW) {
self.firstname = [NSString stringWithUTF8String:(char *)sqlite3_column_text(init_statement, 0)];
self.lastname = [NSString stringWithUTF8String:(char *)sqlite3_column_text(init_statement, 1)];
double dateTest = sqlite3_column_bytes(init_statement, 3);
if (dateTest != 0)
self.birthdate = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_double(init_statement, 3)];
else {
self.birthdate = nil;
}
dateTest = sqlite3_column_bytes(init_statement, 4);
if (dateTest != 0)
self.lastdate = [NSDate dateWithTimeIntervalSince1970:sqlite3_column_double(init_statement, 4)];
else {
self.lastdate = nil;
}
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(init_statement, 2) length:sqlite3_column_bytes(init_statement, 2)];
if(data == nil)
self.picture = nil;
//[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"default_person_picture.png" ofType:nil]];
else {
self.picture = [UIImage imageWithData:data];
[data release];
}
self.father_id = sqlite3_column_int(init_statement, 5);
self.mother_id = sqlite3_column_int(init_statement, 6);
self.sex = [NSString stringWithUTF8String:(char *)sqlite3_column_text(init_statement, 7)];
if (sqlite3_column_int(init_statement, 8) == 1) self.me = YES;
dirty = NO;
}
}
return self;
}
Thanks in advance for your help.
Regards,
Didier