views:

56

answers:

3

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.

+2  A: 

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).

Vladimir
At least in a sample "dummy" class it works :)
Vladimir
+4  A: 

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 pile of excrement:

while([self retainCount] != 0){[self release];}

is truly disastrous. The retain counts of objects never go down to 0. The logic of -release looks something like this:

-release
{
    if (retainCount == 1)
    {
        [self dealloc];
    }
    else
    {
        retainCount--;
    }
}

All other things being equal, the above while 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.

JeremyP
What about `while([self retainCount] != 0){[self release];}`?
Time Machine
@Koning Baard: **No!** That's just as bad. I'll edit my answer to explain why.
JeremyP
"Pile of excrement" barely does justice to how wrong that is... :)
bbum
A: 

As Vladimir stated you should never call dealloc directly. when retain count of an object reaches 0, Cocoa automatically calls dealloc.

Sepehr