Вызываете dealloc в init? - PullRequest
       32

Вызываете dealloc в init?

0 голосов
/ 28 октября 2010

Я пишу каркас, и у меня есть объект с пользовательским методом init:

@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

Безопасно ли вызывать dealloc внутри метода init, если произошла ошибка?Я не уверен в этом, и управление памятью - одна из самых важных вещей в моей жизни.

Спасибо.

Ответы [ 3 ]

6 голосов
/ 28 октября 2010

Безопасно ли вызывать dealloc внутри метода init, если произошла ошибка?

Нет. отправь -release как и везде. Даже в -init вы не можете гарантировать, что текущий счет удержания равен 1.


Почему вы никогда не должны отправлять -dealloc кроме [super dealloc] в -dealloc? Причина в том, что вы никогда не сможете гарантировать, что что-то еще имеет ссылку на ваш объект, даже в -init вашего объекта, потому что [super init] может решить сохранить объект.

Если объект, возвращаемый [super init], имеет счет сохранения 1, отправка -release будет иметь тот же эффект, что и отправка -dealloc. Если он имеет счет сохранения больше 1, кто-то еще думает, что он владеет объектом, и отмена его обращения оставит его с недопустимым указателем, поэтому -release все еще остается правильным.

Также это:

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

приведет к бесконечному циклу и является ужасной идеей по ряду причин. Число сохраняемых объектов никогда не уменьшается до 0. -release выглядит примерно так:

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

так что цикл будет уменьшать счет сохранения до 1, а затем постоянно вызывать dealloc навсегда или до тех пор, пока повреждение кучи, которое он вызвал, не приведет к ошибке сегмента.

Помимо того, что никогда не достигнет нуля, значение retain может быть UINT_MAX (например, в строковых или числовых литералах), что в разговорной речи означает «этот объект никогда не должен быть освобожден». Если счетчик удержания равен UINT_MAX, -release не уменьшит его.

2 голосов
/ 28 октября 2010

Для каждого документа вы никогда не должны вызывать dealloc напрямую - только метод [super dealloc] в вашем пользовательском dealloc.

Я думаю, что вместо этого release должен делать то, что ожидал (по крайней мере, если вы используете метод init только в стандартном шаблоне alloc-init).

0 голосов
/ 29 октября 2010

Как сказал Владимир, вы никогда не должны звонить dealloc напрямую.когда счетчик объектов достигает 0, Какао автоматически вызывает dealloc.

...