I am writing a framework and I have an object with a custom init method:
@implementation OSDatabase
@synthesize database;
// MEM
- (void)dealloc {
sqlite3_close(database);
[super dealloc];
}
// INIT
- (id)initWithDatabasePath:(NSString *)path error:(NSError **)error {
if (self = [super init]) {
if (!sqlite3_open_v2([path UTF8String], &database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
error = [NSError errorWithDomain:@"OSDatabaseErrorDomain" code:1 userInfo:nil];
[self dealloc];
return nil;
}
}
return self;
}
@end
Is it safe to call dealloc inside of an init method if an error occoured? I’m not sure about this and memory management is one of the most important things in my life.
Thanks.
No. send
-releaselike you would everywhere else. Even in-inityou can’t guarantee that the current retain count is 1.Why must you never ever send
-deallocexcept[super dealloc]in-dealloc? The reason is that you cannot ever guarantee that something else also has a reference to your object, even in your object’s-initbecause the[super init]might choose to retain the object.If the object returned by
[super init]has a retain count of 1, sending-releasewill have the same effect as sending-dealloc. If it has a retain count of more than 1, something else thinks it owns the object and deallocing it would leave it with an invalid pointer, so-releaseis still the right thing to do.Also, this:
would result in an infinite loop and is a terrible idea for a number of reasons. The retain counts of objects never go down to 0.
-releaselooks something like this:so the loop will decrement the retain count to 1 and then continually call dealloc forever or until the heap corruption it has caused leads to a seg fault.
Apart from never reaching zero, the retain may be
UINT_MAX(for example in string or numeric literals) which colloquially means “this object must never be deallocated”. If the retain count isUINT_MAX,-releasewon’t decrement it.