В чем заключается необходимость назначения "nil" после отпускания объекта
Я обычно освобождаю объект после использования
[myObject release];
Но я нашел в некоторых онлайн-уроках, что они назначают nil после отпускания объекта. Как
[myObject release];
myObject = nil;
Требуется ли?
Ответы
Ответ 1
Это долгая дискуссия о том, нужна ли установка указателя на nil
после освобождения, но я склоняюсь к тому, что это хорошая идея.
После того, как объект будет выпущен, указатель, который вы удерживаете на нем, по-прежнему указывает на то же место. Если ваш релиз взял счетчик удержания до 0, объект будет освобожден. Если вы затем попытаетесь отправить сообщение на освобожденный объект, вы получите ошибку EXC_BAD_ACCESS. Однако отправка сообщения указателю после того, как он был установлен на nil
, не будет ошибкой - он ничего не сделает.
Другая сторона аргумента состоит в том, что если вы отправляете сообщение об освобожденном объекте, хорошо знать об этом и исправить свой код, чтобы убедиться, что этого не происходит.
В обоих лагерях есть умные люди.
Ответ 2
Нет, это не обязательно.
Если ваш код хорошо структурирован, нет необходимости принуждать myObject
к нулю.
Однако это может быть хорошей привычкой: release
не сразу уничтожает объект, просто уменьшает счетчик retain
. Таким образом, может быть, что даже если вы вызываете release, объект все равно будет там некоторое время, создавая проблемы, если вы попытаетесь отправить его сообщениям.
Использование myObject = nil;
устраняет эту проблему, так как даже если вы отправляете сообщение на myObject
, ничего не произойдет.
Ответ 3
Это не требуется, но в основном проблема стиля. Присвоение nil
после освобождения гарантирует, что вы не можете случайно использовать освобожденную ссылку еще раз (что может или не может привести к сбою). Просто вызов release
в ссылке может привести к тому, что основная память исчезнет. Однако указатель будет по-прежнему указывать на (теперь потенциально недействительный) адрес, а результат последующего вызова метода с использованием этого указателя undefined.
Ответ 4
Нет, это не требуется.
Это вещь безопасности. Если у вас есть
[myObject release];
а затем в другом месте вы
[myObject doSomething];
Тогда у вас появятся проблемы.
Если у вас
[myObject release];
myObject = nil;
а затем в другом месте вы
[myObject doSomething];
Тогда ничего не произойдет, потому что вы вызываете объект nil. Таким образом, ваше приложение не просто упадет в большой куче. Или если у вас есть где-то еще в коде
[myObject release];
Затем он будет выпущен на ноль-объекте и поэтому не будет перевыпускать.
Очевидно, вам следует просто не называть объект, который вы уже выпустили!
Ответ 5
Я всегда был бы нулевым.
Яблоко себя иногда (задокументировано) проверяет на отсутствие.
Пример
Если вы установите для параметра navigationItem.titleView
значение nil
, чтобы вернуться к использованию navigationItem.title
, или ваш заголовок не будет отображаться.
В документации Apple есть много ссылок на эту "проверку нуля".
Ссылка
https://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationItem_Class/Reference/UINavigationItem.html
Восстановление navigationItem.title после удаления navigationItem.titleView
Ответ 6
не очень, но лучше использовать его для предотвращения ошибок...
если вы вызываете где-то в свой код myObject, когда он был выпущен, он дает вам плохую ошибку,
но если он будет установлен на ноль, ошибка может быть обходится
если вы попытаетесь:
myObject.someProperty = 1;
или
if (myObject) {...}
и вы только что выпустили myObject, это просто может привести к сбою вашего приложения...
Ответ 7
Это не требуется, но обычно считается хорошей практикой во всех средах, за исключением того, что он обычно считается ненужным в методе -dealloc
.
Причина, по которой обычно устанавливается указатель объекта на nil после выпуска, потому что диспетчер методов Objective-C не пытается отправить сообщение объекту nil, что означает, что вы можете случайно использовать объект позже.
Ответ 8
после выпуска abject, но не назначает NULL, он сохраняет адрес, но контент освобождается. Таким образом, теперь он не указывает на какое-либо допустимое место в памяти. Хранение ptr теперь висит указателем, который, вероятно, имеет адрес, но не указывает на какое-либо действительное место в памяти.
поэтому рекомендуется назначить NULL после освобождения выделенной памяти ниже
PTR = NULL;
таким образом, проблема будет виновата.
Ответ 9
Я бы предложил гибридный подход. Давайте рассмотрим типичные требования к приложениям:
- Мы хотим минимизировать сбои приложений в производстве
- Мы хотим поймать проблемы, такие как доступ к потенциально выпущенной памяти, а мы тестируем
Хорошим решением является условное назначение:
- Nil в выпусках
- Умышленно плохой указатель (например, 0x20) при отладке.
Это обеспечивает стабильность в производственных сборках, но в режиме отладки любая попытка получить доступ к переменной приведет к краху приложения. Обратите внимание, что вызов release на объекте не гарантирует, что память объекта будет удалена, поэтому необходимо явно установить неправильный указатель.
#ifdef DEBUG
#define RELEASE(obj) [(obj) release]; (obj) = (id)0x20;
#else
#define RELEASE(obj) [(obj) release]; (obj) = nil;
#endif
Ответ 10
На Apple Tech Talk я пошел пару лет назад, инженеры Apple обсудили несколько примеров, когда было необходимо назначить nil, но я не могу вспомнить детали, кроме того, что он был внутри dealloc в обсуждаемых случаях, Достаточно сказать, что не правильно говорить, что вам никогда не приходилось это делать или что это плохая практика. Иногда вам нужно. Но в большинстве случаев вам это не нужно. Извините, моя память неясна.