问题
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.
回答1:
Is it safe to call dealloc inside of an init method if an error occoured?
No. send -release
like you would everywhere else. Even in -init
you can't guarantee that the current retain count is 1.
Why must you never ever send -dealloc
except [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 -init
because the [super init]
might choose to retain the object.
If the object returned by [super init]
has a retain count of 1, sending -release
will 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 -release
is still the right thing to do.
Also, this:
while([self retainCount] != 0){[self release];}
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. -release
looks something like this:
- (id)release
{
if (retainCount == 1)
{
[self dealloc];
}
else
{
retainCount--;
}
}
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 is UINT_MAX
, -release
won't decrement it.
回答2:
Per docs you should never call dealloc directly - only [super dealloc]
method in your custom dealloc.
I think calling release
instead should do what expected (at least if you use init method only in standard alloc-init pattern).
回答3:
As Vladimir stated you should never call dealloc
directly. when retain count of an object reaches 0, Cocoa automatically calls dealloc
.
来源:https://stackoverflow.com/questions/4042934/calling-dealloc-in-init