2010-10-28 5 views
0

Я пишу рамки и у меня есть объект с методом пользовательского INIT:Вызов dealloc в 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 метода, если ошибка occoured? Я не уверен в этом, и управление памятью - одна из самых важных вещей в моей жизни.

Спасибо.

ответ

6

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

No. отправить -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 навсегда или до коррупции кучи не вызвавший приводит к сбой.

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

+0

Как насчет 'while ([self retainCount]! = 0) {[self release];}'? –

+0

@ Koning Baard: ** Нет! ** Это так же плохо. Я отредактирую свой ответ, чтобы объяснить, почему. – JeremyP

+0

«Куча экскрементов» едва ли оправдывает то, как это неправильно ...:) – bbum

2

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

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

+0

По крайней мере, в образце «фиктивный» класс работает :) – Vladimir

0

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

 Смежные вопросы

  • Нет связанных вопросов^_^