2011-02-21 2 views
6

Довольно много людей, кажется, использовать макрос, такие какНам действительно нужен безопасный макрос релиза?

#define SAFE_RELEASE(X) [X release]; X = nil; 

(включая меня).

Я пересматриваю, почему я его использую, и хотел, чтобы на холсте было какое-то мнение.

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

Мне кажется, что это может замаскировать некоторые неясные ошибки. Возможно, на самом деле было бы предпочтительнее, если бы программа сработала, когда вы снова попытаетесь использовать X. Таким образом, во время тестирования вы можете найти проблему и улучшить код.

Поддерживает ли этот макрос ленивое программирование?

Мысли?

+1

Соответствующий раздел в [FAQ] (http://stackoverflow.com/faq) для вопросов, которые не должны быть заданные здесь. - «Нет реальной проблемы, которую нужно решить:« Мне любопытно, если другие люди чувствуют себя так ». – Abizern

+0

Достаточно честный, но это проблема, с которой я столкнулся. Проблема в том, следует ли продолжать использовать этот макрос? Есть ли веские причины использовать его, о котором я не знаю? – Ian1971

ответ

6

Думаю, вы обсудите все плюсы и минусы в своем вопросе, поэтому у меня нет большой суммы для добавления. Лично я не использую конструкцию. Как вы полагаете, может использовать для работы над областями, где люди не понимают правильность управления памятью. Мое предпочтение - исправить ошибку, а не симптом.

Однако один компромисс, который я видел, время от времени:

  • Сделать аварии во время разработки
  • Проделайте var = nil; в производстве код

Таким образом, он мощь быть более надежным с оплатой клиентов и все еще выходить из строя на раннем этапе разработки.

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

+0

Я согласен Мне не нравится иметь разный код по продукции – Ian1971

+0

Почему проголосовали? –

1

Вам не нужно его, но это удобно. Я использую что-то подобное в своих приложениях. Вы можете считать это «ленивым», но когда у вас где-то около 20 объектов, запись их вручную становится утомительной.

+1

Я предполагаю, что речь идет не только о макросе, но и о теории установки объекта на нуль после его выпуска. Если вы закончили с объектом, возможно, вам не следует пытаться получить к нему доступ еще раз, и если вы снова получите доступ к нему, тогда лучше всего иметь сбой, чтобы вы могли разобраться в этой конкретной проблеме с кодом. например, почему вы пытаетесь получить к нему доступ еще раз? – Ian1971

2

Я думаю, что это или эквивалент, такой как self.myVar = nil, где это применимо, является хорошим. Есть много случаев, когда вы просто не можете просто назначить nil и предположить, что какой-либо более поздний доступ является ошибкой.

Например, в UIKit это хорошее поведение, чтобы освободить как можно больше ресурсов, когда ОС спросит. Например.

- (void)didReceiveMemoryWarning 
{ 
    [myCachedData release]; 
    [super didReceiveMemoryWarning]; 
} 

Теперь, когда мой класс используется следующим образом, как я могу узнать, что myCachedData теперь недействительна? Единственный способ (не имеющий переменной ANOTHER, действующий как флаг) - установить myCachedData на нуль после его выпуска. И конденсация этих двух утомительных линий в одну - это именно то, для чего SAFE_RELEASE.

+0

Я думаю, что вы правы, правильно установить нуль, где это применимо. Я думаю, что ловушка, в которую я попал, слепо использовала макрос и не слишком много думала об этом. – Ian1971

1

Я изучал тот же вопрос.С небольшим количеством чтения я сделал я только что-то вроде этого:

#define DEBUGGING 
    //#define PRODUCTION 

#ifdef DEBUGGING 
#define SAFE_RELEASE(X) [X release]; 
#else 
#define SAFE_RELEASE(X) [X release]; X = nil; 
#endif 

Так что путь, если я разрабатываю, я получаю Аварии. В производстве я этого не делаю.

< Скотт -

+0

Это может привести к очень сложному отслеживанию ошибок при производстве - см. Мой ответ для деталей. – Sebastian

1

Как отметил Андрей, есть случаи, когда назначая nil не только избежать ошибок, но и необходимо. Просто рассмотрим типичное UIViewController код

- (void)viewDidLoad { 
    button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // autoreleased 
    [button retain]; // keep alive 
} 

- (void)viewDidUnload { // view has been removed 
    [button release]; 
} 

- (void)dealloc {  // destroying the view controller 
    [button release]; // <-- problem 
} 

В случае загрузки контроллера, а затем выгружается (потому что другой контроллер представления отображается память при низком уровне) и, наконец, разрушен, [button release] в dealloc бы чрезмерно отпустить кнопку (отправить сообщение выпущенному объекту). Поэтому необходимо назначить nil. Безопасным решением будет:

- (void)viewDidUnload { // view has been removed 
    [button release]; 
    button = nil; 
} 

- (void)dealloc {  // destroying the view controller 
    [button release]; // <-- safe 
} 

Для этих случаев макрос приятный и полезный. Чтобы быть более четко о том, что он делает, лучше назвать это RELEASE_AND_NIL

#define RELEASE_AND_NIL(X) [X release]; X = nil; 
Смежные вопросы