Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top