Что произойдет, если вы попытаетесь освободить объект, который был освобожден? - PullRequest
1 голос
/ 29 мая 2011

Что, если у меня есть объект, скажем NSIndexPath, в котором перед тем, как сделать копию, я всегда сначала выпускаю ее?

Можно ли иметь счетчик памяти меньше 0?Я делаю это для предотвращения утечек памяти ... это хороший способ?

// глобальный уже имеет какое-то значение здесь или не имеет значения .. Я хочу обновить
// это с новым значением (мне больше не нужен старый указатель)

 [global release]
 global = [indexPath copy];

Ответы [ 2 ]

8 голосов
/ 29 мая 2011

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

Вам следует прочитать Управление памятью AppleGuide .

Это фундаментальное правило:

  • Вы отпускаете или автоматически выпускаете только свои собственные объекты.Вы вступаете во владение объектом, если создаете его с помощью метода, имя которого начинается с «alloc», «new», «copy» или «mutableCopy» (например, alloc, newObject или mutableCopy), или если вы отправляете егосообщение о сохранении.
  • Вы используете release или autorelease, чтобы отказаться от владения объектом.«autorelease» означает просто «отправить сообщение о выпуске в будущем» (в частности, когда используемый пул автоматического выпуска получает сообщение об утечке).

Обновление:

Как указал Джош, один случай, который вам нужно рассмотреть, - это когда global и indexPath совпадают.В этом случае вам все равно «понадобится» указатель (для выполнения копирования), поэтому вы либо автоматически выпускаете его (вместо освобождения), либо используете временную переменную для обработки этого.

0 голосов
/ 30 мая 2011

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

// global points to object at 0x8BADFOOD
// indexPath also happens to be 0x8BADFOOD; for some reason, it
// hasn't changed since last time. This _can_ happen.
[global release];    // object at 0x8BADFOOD is deallocated
global = [indexPath copy];    // indexPath no longer valid! 
                              // Crash! Bang! Boom!

Способизбежать этого - использовать временную переменную.

Когда вы объявляете свойство как copy и синтезируете это свойство, созданный метод установки выглядит по сути так, и вы можете сделать то же самое:

- (void)setMyFloozit:(Floozit *)newFloozit {
    // Copy first in case newFloozit and myFloozit are for
    // some reason the same object
    // Take ownership of a copy of newFloozit
    Floozit * tmp = [newFloozit copy];
    // We no longer need old value of myFloozit, so we release it.
    [myFloozit release]; 
    // tmp contains a value that we own, we just need to assign
    // it to the correct name.
    myFloozit = tmp;
}

Это можно сделать немного лучше, сначала проверив, одинаковы ли newFloozit и myFloozit, и ничего не сделав, если они есть.

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