Нам действительно нужен безопасный релиз макроса? - PullRequest
6 голосов
/ 21 февраля 2011

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

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

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

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

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

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

Этот макрос поощряет ленивое программирование?

Мысли

Ответы [ 5 ]

6 голосов
/ 21 февраля 2011

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

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

  • Заставьте его падать во время разработки
  • Выполните var = nil; в производственном коде

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

2 голосов
/ 02 марта 2011

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

Например, в UIKit хорошо, когда система запрашивает столько ресурсов, сколько возможно. Э.Г.

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

Теперь, когда в следующий раз будет использован мой класс, как я узнаю, что myCachedData теперь недействителен? Единственный способ (если не считать ДРУГОЙ переменной, действующей в качестве флага) - установить myCachedData равным nil после его освобождения. А сжатие этих двух утомительных строк в одну - это именно то, для чего SAFE_RELEASE.

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

Как отметил Эндрю, есть случаи, когда назначение 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 приведет к чрезмерному отпусканию кнопки (отправит сообщение освобожденному объект). Поэтому необходимо назначить ноль. Безопасное решение будет:

- (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;
1 голос
/ 23 сентября 2011

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

#define DEBUGGING
    //#define PRODUCTION

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

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

Scott <- </p>

1 голос
/ 21 февраля 2011

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

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