2013-02-12 2 views
0

Недавно я столкнулся с this blog post, где обсуждаются два варианта освобождения переменных экземпляра. Чтобы дать Вам резюме:В выражениях, разделенных запятыми в Objective-C

Первый подход

- (void)dealloc { 
    [instanceVar release]; 
    [super dealloc]; 
} 

считается не оставить указатель живым до возвращения метода. Это может привести к неопределенному поведению. Второй подход

- (void)dealloc { 
    [instanceVar release], instanceVar = nil; 
    [super dealloc]; 
} 

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

OK. Вот вопрос, который вы ждете: Оба решения одинаковы? Или разделение запятой выражений делает их атомарными?

ответ

1

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

С ARC это еще менее проблематично. Метод dealloc в ARC используется только для освобождения ресурсов, не поддерживающих ARC, все остальное автоматически обрабатывается для вас.

+0

Да. Это уже упоминалось в упомянутом сообщении в блоге. Не могли бы вы (теоретически) получить ситуацию, когда вы используете значение _dangling_, прежде чем instanceVar будет установлен в nil? – lupz

+0

@ lupz: Вы * можете *, теоретически у вас могло бы быть два потока, один из которых переопределил объект и вызвал 'dealloc' в одном потоке, в то время как' instanceVar' все еще используется в другом потоке. Обратите внимание, что это может проявиться только в результате ошибки переизбытка одного потока. Установка 'instanceVar' на' nil' только изменяет поведение ошибки, она на самом деле ничего не решает. – dreamlax

2

Сообщение в блоге связывании от 2010

Более интересным моментом является то, что в настоящее время вы должны сделать ни. Если вы используете ARC, вы не можете отправить сообщение об освобождении объектам.

Установка nil после освобождения была предназначена для предотвращения отправки неконсервированных объектов сообщения после того, как они были освобождены и вызвали сбой. Я говорю не удерживаемые объекты, потому что если бы они были сохранены, они не были бы (не должны) освобождаться неосознанно. Опять же, с ARC (до тех пор, пока вы не используете ARC-lite), вы можете пометить не удерживаемые объекты как weak, а слабые указатели - авто-ноль; то есть когда объект, на который они указывают, освобождается, указатель устанавливается на nil.

Таким образом, второй случай с указателями, установленными на nil после dealloc, считается более безопасным во время выполнения, но вам не нужно беспокоиться об этом сейчас, поскольку ARC обрабатывает это для вас.

+0

Я не обязательно думаю, что это безопаснее. Если что-то полагается на память, этого не должно быть, вы только изменяете поведение этой ошибки, меняя ее на «nil». У вас есть ошибка в любом случае. Хотя сообщения в no-op безопасны, предоставление этого объекта методам, которые не ожидают «nil», по-прежнему будут приводить к нежелательным результатам (например, 'rangeOfString:' генерирует исключение, если аргумент равен «nil»). – dreamlax

+0

В этом его смысл - это безопаснее во время выполнения, но если вы позволите исключить исключение, тогда в процессе разработки будет найдена ошибка (если таковая имеется). Но с АРК уже нет таких дебатов. – Abizern

+0

@Abizem: Я имею в виду, что это не * безопаснее * в том смысле, что установочные указатели на 'nil' сделаны только из надежды, что * если * что-то должно было полагаться на обвисший указатель, который« ущерб »выиграл, t быть так же плохо, но на самом деле вы должны гарантировать, что * ничего * будет использовать обвисший указатель, т. е. если ваша программа использует освобожденный объект, ваша программа имеет ошибку. Все, что вы делаете, устанавливая указатель на нуль, меняет способ проявления ошибки, и если вы только устанавливаете его на нуль в сборках релизов, вы только гарантируете, что ошибка ведет себя по-разному между сборками релизов и отладки. – dreamlax

Смежные вопросы