I have a class that manages the database queries for my project and I’m having some issues with memory management and the [return autorelease]part of the code. I don’t know how to return an object to the calling function but it uses it afterwards.
The code is this:
-(Hexagram *)getHexagramforId:(NSInteger)hexagramNumber{
Hexagram *current;
if (init_statement == nil) {
const char * sql = "SELECT * FROM HEXNUMBER where _id =?";
if (sqlite3_prepare_v2(database, sql, -1, &init_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error:failed to prepare argument with message %s", sqlite3_errmsg(database));
}
sqlite3_bind_int(init_statement, 1, hexagramNumber);
if (sqlite3_step(init_statement) == SQLITE_ROW) {
current = [[Hexagram alloc]initWithId:hexagramNumber
Title:[NSString stringWithUTF8String:(char*)sqlite3_column_text(init_statement, HEX_TITLE)]
LongText:[NSString stringWithUTF8String:(char*)sqlite3_column_text(init_statement, HEX_TEXT)]ShortText:nil InternalColor:sqlite3_column_int(init_statement, INTERNAL_COLOR) ExternalColor:sqlite3_column_int(init_statement, EXTERNAL_COLOR)];
}else{
NSAssert1(0, @"Database is corrupt, error %s", sqlite3_errmsg(database));
}
sqlite3_reset(init_statement);
sqlite3_close(database);
init_statement = nil;
return current;
}
return nil;
}
So what happens is in the analyzer it says that the object current hexagram is leaked, but if I return it with an autorelease it crashes. I want to support iOS < 5 so I don’t want to use ARC but so far I don’t know how to return this object and not get this error in the static analyzer. Any help please?
First off, the reason the analyzer is complaining is because you’re creating your
Hexagramobject viaalloc] init, and returning it like that, which means your object will start out with a retain count of 1. Unless your method names starts with new/alloc/copy, the user of the code (and static analyzer) will be expecting an autoreleased object. (See documentation of naming conventions + memory management).As for autorelease; Autorelease will give an object a retain count of 1 (so that it can hang around for a bit), but will be released at the end of a run loop. This will cause a retain count of 0, and the object gets deallocated.
Now, why does
return [current autorelease]fail? The reason will be because of the caller of the methodgetHexagramforId. If someone is calling a method that returns an autoreleased object (a method that does not start with new/alloc/copy etc…), then it is their responsibility to keep hold of that object when it needs to (for the reasons mentioned above).So for example, if you changed
return currenttoreturn [current autorelease], and called the method as so:your program shouldn’t crash. You are explicitly retaining an autoreleased object, so you now can keep that object around, until you no longer need it. At that point, call
[obj release].Other methods for retaining an autoreleased object include assigning it to a retaining property, as so: