Release, Dealloc и ссылка на себя - PullRequest
33 голосов
/ 31 июля 2009

Так что я подумал, что все эти вопросы прояснены. Затем внезапно я получаю ошибку (сбой), которую я не могу понять. Затем, выполнив исследование по устранению аварии, я заметил, что все, что, как я думал, я знал об этих критических областях, несколько ошибочно.

Ниже приведены 8 вопросов, которые я просто собираюсь ответить на них в надежде, что кто-нибудь ответит - ответы на них очень помогут мне вернуть мое понимание в нужное русло. Спасибо заранее!

Q1) Можно ли вызвать Release для объекта, если эта ссылка равна нулю? Это должно быть безвредно, верно?

Q2) Можно ли вызвать Release для объекта, если эта ссылка была освобождена и в качестве счетчика ссылок 0?

Q3) Необходимо ли устанавливать ссылку на ноль ПОСЛЕ отпускания? Что произойдет, если вы не установите его на ноль?

Q4) Есть ли разница между nil и NULL или это просто семантическая вещь, помогающая читателю / разработчику узнать тип объекта, просто взглянув на него?

Q5) Использование свойств ТРЕБУЕТСЯ использовать указатель «Self»?

Q6) Использование переменных экземпляра требует, чтобы указатель «Self» НЕ использовался?

В7) Когда я захочу использовать переменную экземпляра вместо ее свойства? Я полагаю, что члены с типом значения в порядке, поскольку они не выпускаются и не сохраняются.

Q8) Нужно ли вызывать коллелоц объекта из функции деаллока? Во многих примерах я видел, как вызывается Release, но не Dealloc - такие учебники некорректны?

Ответы [ 5 ]

19 голосов
/ 31 июля 2009

А1) [nil release] нормально (ничего не сделает)

A2) Нет. Не трогайте объекты после того, как они были освобождены. Они должны быть равны нулю после освобождения.

A3) Нет необходимости устанавливать освобожденный указатель на ноль, но вы получаете висячие указатели (т.е. вы не можете определить, является ли объект действительным или нет). Установка свойства в nil часто используется для освобождения базового ivar, поэтому, если это не сделать, это может привести к утечке памяти

A4) nil и NULL оба равны нулю, поэтому технически одинаковы.

A5) Да, вы должны использовать self.someProperty для свойств, так же, как вы использовали бы [self someProperty], если бы это был просто метод

A6) self - это, по сути, структура, поэтому вы можете получить доступ к ivars следующим образом: self->someIvar. В этом нет необходимости.

A7) Когда вы не хотите запускать методы установки / получения по какой-либо причине. Иногда я использую его, когда установщик не допускает значений nil, и мне нужно освободить переменную

A8) dealloc вызывается автоматически, когда release вызывается с правильным количеством раз. Вы никогда не должны вызывать dealloc напрямую (кроме [super dealloc])

11 голосов
/ 31 июля 2009

Возможно, вам следовало разделить этот вопрос на несколько разных вопросов, но я укушу.

  1. Да, любое сообщение, отправленное на nil, не разрешено.
  2. Нет. Объект с ref-count 0 был или неизбежно будет уничтожен, и любые отправленные ему сообщения вызовут сбой или, в лучшем случае, исключение.
  3. Это зависит от ситуации. Если вы выпускаете вещи в -dealloc, то, вероятно, нет. Если это объект, относящийся к определенному методу, то, вероятно, нет. Если это ивар, который используется повторно, я бы сказал да. В первых двух случаях ничего не произойдет, если вы не установите указатели на ноль, поскольку вы обычно больше не сможете получить доступ к этим указателям. В последнем случае вы все равно можете получить доступ к указателю, который указывает на освобожденную память. Если вы отправите ему сообщение или попытаетесь разыменовать его, ваше приложение упадет.
  4. Они оба равны 0. По соглашению nil используется для указателей объектов, а NULL используется для любых других указателей, но смешивание их не вызовет никаких проблем.
  5. Если вы хотите вызвать свойство getter / setter, тогда да. Если вы хотите получить доступ к ivar, он инкапсулируется напрямую (редко), нет.
  6. Нет, вы можете получить доступ к переменным экземпляра, используя синтаксис self->ivar. Фактически, когда вы набираете просто ivar, компилятор неявно добавляет разыменование self->.
  7. Не уверен, что вы имеете в виду здесь.
  8. Единственный раз, когда вы должны вызывать -dealloc, это когда вы вызываете [super dealloc]; в ваших собственных -dealloc методах. Для любых других объектов вы всегда должны просто позвонить -release.
8 голосов
/ 31 июля 2009

Другие ответили 1-6 адекватно.

(7) Apple рекомендует использовать переменную экземпляра напрямую как в init, так и в dealloc. В первую очередь это связано с тем, что объект (особенно если он подклассифицирован) настраивается только частично во время обоих этих методов, и поэтому вызов метода установки / получения может привести к некорректному поведению, если у них есть что-то кроме тривиальных действий. Как правило, вы можете безопасно получить доступ к ивуру напрямую (а не через геттер) в вашем объекте, и это будет незначительно эффективнее (только на iPhone). Как правило, вы должны использовать сеттер во всех случаях, особенно если ваш объект может быть разделен на подклассы или если другие могут наблюдать свойство.

(8) Вы никогда не вызываете dealloc (кроме [super dealloc] из метода dealloc). Если у вас есть право собственности на другой объект, вы должны отказаться от него (позвонив в release или autorelease). Затем система вызовет Deloc на объекте, если это необходимо. Но ты никогда не звонишь в Деллок самостоятельно. Прочитайте правила управления памятью (всего 9 параграфов, которые необходимо понять).

0 голосов
/ 06 мая 2014

А4) Они различаются по своим типам. Все они равны нулю, но NULL - это пустота *, nil - это идентификатор, а Nil - указатель класса.

0 голосов
/ 01 августа 2009

Хорошо. Я подтвердил, что не установка B на ноль сделала свое дело. Итак, теперь я не проверяю nil при создании контроллера B (когда я хочу перейти к нему).

Вместо этого я отпускаю B, затем создаю контроллер и назначаю его B. Затем в методе viewDidAppear A я выпускаю B.

Я считаю, что эта тема закрыта. Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...