开发者

Calling dealloc in init?

I am 开发者_Go百科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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜