Calling dealloc in init?

谁说胖子不能爱 提交于 2019-12-02 19:30:41

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!