В чем заключается необходимость назначения "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 в обсуждаемых случаях, Достаточно сказать, что не правильно говорить, что вам никогда не приходилось это делать или что это плохая практика. Иногда вам нужно. Но в большинстве случаев вам это не нужно. Извините, моя память неясна.