Безопасно ли вызывать 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
не уменьшит его.