Что нужно присвоить «ноль» после освобождения объекта - PullRequest
11 голосов
/ 14 февраля 2012

Я обычно освобождаю объект после использования

[myObject release];

Но я обнаружил в некоторых онлайн-уроках, что они присваивают nil после освобождения объекта. Как

[myObject release];
myObject = nil;

Требуется ли?

Ответы [ 10 ]

29 голосов
/ 14 февраля 2012

Это длительная дискуссия о том, необходимо ли устанавливать указатель на nil после освобождения, но я считаю, что это хорошая идея.

После того, как объект отпущен, указатель, который вы держите на нем, все еще указывает на то же место. Если в вашем выпуске счетчик удержаний был равен 0, то объект будет освобожден. Если вы попытаетесь отправить сообщение освобожденному объекту, вы получите ошибку EXC_BAD_ACCESS. Однако отправка сообщения указателю после того, как ему присвоено значение nil, не приведет к ошибке - оно просто ничего не сделает.

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

В обоих лагерях есть умные люди.

3 голосов
/ 14 февраля 2012

Нет, это не обязательно.
Если ваш код хорошо структурирован, нет необходимости заставлять myObject быть равным нулю.

Однако это может быть хорошей привычкой: release не сразу уничтожает объект, просто уменьшаетколичество retainТаким образом, может случиться так, что, даже если вы вызовете release, объект все еще будет там некоторое время, создавая проблемы, если вы попытаетесь отправить ему сообщения.

Использование myObject = nil; устранит эту проблему, поскольку дажеесли вы отправите сообщение на myObject, на самом деле ничего не произойдет.

2 голосов
/ 14 февраля 2012

Я бы всегда устанавливал на ноль.

Apple иногда (документально) проверяет наличие нуля.

Пример;

Если вы установите navigationItem.titleView, необходимо установить значение nil, если вы хотите вернуться к использованию navigationItem.title, иначе ваш заголовок не будет отображаться.

В документации Apple есть много ссылок на эту «проверку на ноль».

Ссылка;

https://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationItem_Class/Reference/UINavigationItem.html

Восстановление элемента навигации.title после удаления navigationItem.titleView

2 голосов
/ 14 февраля 2012

Нет, это не требуется.

Это вопрос безопасности.Если у вас есть

[myObject release];

, а затем в другом месте вы делаете

[myObject doSomething];

Тогда у вас возникнут проблемы.

Если у вас есть

[myObject release];
myObject = nil;

а затем где-то еще вы делаете

[myObject doSomething];

Тогда ничего не произойдет, потому что вы вызываете нулевой объект.Так что ваше приложение не просто упадет в большую кучу.Или, если у вас есть где-то еще в коде

[myObject release];

, тогда он будет освобожден для нулевого объекта и не будет перевыпущен.

Очевидно, вам следует просто избегать вызоваобъект, который вы уже выпустили!

2 голосов
/ 14 февраля 2012

Это не обязательно, но в основном проблема стиля.Назначение nil после выпуска гарантирует, что вы не сможете случайно использовать освобожденную ссылку снова (что может привести к сбоям или не привести к сбоям).Простой вызов release для ссылки может привести к потере основной памяти.Однако указатель все равно будет указывать на (теперь потенциально недействительный) адрес, и результат последующего вызова метода с использованием этого указателя не определен.

1 голос
/ 14 февраля 2012

Это не требуется, но обычно считается хорошей практикой во всех средах, за исключением того, что в методе -dealloc это обычно считается ненужным.

Причина, по которой обычно устанавливается нулевой указатель объекта после освобождения, заключается в том, что диспетчер метода Objective C не будет пытаться отправить сообщение нулевому объекту, что означает, что вы можете случайно использоватьобъект позже.

1 голос
/ 14 февраля 2012

не совсем, но лучше использовать его для предотвращения ошибок ...

, если вы вызываете где-нибудь в своем коде myObject, когда он был выпущен, это выдаст вам плохую ошибку, но если вы попытаетесь обнулить ошибкуможет обойтись

, если вы попытаетесь:

myObject.someProperty = 1;

или

if (myObject) {...}

, и вы только что выпустили myObject, это может привести к сбою вашего приложения ...

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

Я бы предложил гибридный подход. Давайте посмотрим на типичные требования приложения:

  1. Мы хотим минимизировать сбои приложений на производстве
  2. Мы хотим отследить такие проблемы, как доступ к потенциально освобожденной памяти, пока мы тестируем

Хорошим решением является условное присвоение:

  1. Ноль в релизных сборках
  2. Преднамеренно неверный указатель (например, 0x20) при отладке.

Это обеспечивает стабильность в производственных сборках, но в режиме отладки любая попытка доступа к переменной приведет к явному сбою приложения. Обратите внимание, что вызов release для объекта не гарантирует удаления памяти объекта, поэтому необходимо явно установить неверный указатель.

#ifdef DEBUG
    #define RELEASE(obj) [(obj) release]; (obj) = (id)0x20;
#else
    #define RELEASE(obj) [(obj) release]; (obj) = nil;
#endif
0 голосов
/ 14 февраля 2012

На Apple Tech Talk, которую я посетил пару лет назад, инженеры Apple обсуждали несколько случаев, когда было важно назначить nil, но я не могу вспомнить подробности, отличные от того, что было внутри dealloc в обсуждаемых случаях , Достаточно сказать, что неправильно говорить, что вам это никогда не нужно, или что это плохая практика. Иногда ты должен. Но в большинстве случаев вам не нужно. Извините, моя память не прояснилась.

0 голосов
/ 14 февраля 2012

после освобождения объекта, но без назначения NULL, он сохраняет адрес, но содержимое освобождается. Так что теперь он не указывает ни на одну допустимую ячейку памяти. Hence ptr теперь является висящим указателем, который, вероятно, имеет адрес, но не указывает на какую-либо действительную ячейку памяти. поэтому рекомендуется освободить NULL после освобождения выделенной памяти, как показано ниже

PTR = NULL;

, таким образом, проблема с зависанием будет решена.

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