Цель-C: Что касается памяти, что мне нужно делать с другими указателями на освобожденный объект? - PullRequest
1 голос
/ 15 октября 2010

Например, скажите, у меня есть:

NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableArray *array2 = array;
[array release];

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

Ответы [ 4 ]

2 голосов
/ 15 октября 2010

Как вы подозреваете, array2 больше не ссылается на действительный объект после вызова [array release].

Однако неясно, какое значение имеет вторая переменная. Вам нигде не будет доступно, что array еще не доступно (они имеют одинаковую область видимости), и, поскольку они оба ссылаются на один и тот же объект, вы могли бы просто использовать одну переменную.

Если вам нужен второй массив или другая ссылка, действительная после [array release], вы можете создать копию или использовать NSMutableArray *array2 = [array retain]. В любом случае вам нужно будет освободить array2 в какой-то момент, чтобы избежать утечки памяти.

1 голос
/ 15 октября 2010

Разве это не просто вопрос чистоты кода?

Если вы хотите, чтобы array2 указывала на массив, и вы собираетесь поработать с array2, тогда я бы явно сохранил это:

NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableArray *array2 = [array retain];
[array release];
[array2 release];

Таким образом, если кто-то решит выполнить какую-то работу с array2 после вызова [release release], у него не будет проблем с памятью.

Ваш оригинальный код действителен, но содержит неприятный сюрприз для всех, кто использует array2 после вызова release.

1 голос
/ 15 октября 2010

Вам не нужно ничего делать!

«Другие» указатели ничем не отличаются от исходного указателя. Все они указывают на одно и то же. Они в точности эквивалентны друг другу.

Важно понимать, что release не влияет на сам указатель. У меня создается впечатление, что вы думаете, [array release] как-то что-то делает с указателем array, оставляя его каким-то образом измененным. Это не так. Рассмотрим этот код:

NSMutableArray *array = [[NSMutableArray alloc] init];
NSMutableArray *array2 = array;
[array2 release];

Это в точности соответствует вашему коду и так же законно. Вы можете вызвать релиз по номеру array или array2, и он имеет точно такой же эффект. Ни array, ни array2 не изменяются при вызове. Только объект, на который указывает.

Так что нет смысла удерживать дважды только выпускать дважды. В конце концов, у вас точно такая же ситуация: два указателя на освобожденный объект.

Вы можете обнулять их, если хотите, но в этом нет необходимости.

1 голос
/ 15 октября 2010

Переменные array и array2 - это всего лишь C указатели на кусок памяти.Как и для любого выделенного кучи куска памяти в C, он должен быть malloced () и freed (), которые эффективно определяют время жизни куска памяти в отсутствие сборщика мусора.Объекты Obj-C - это небольшие специализированные куски памяти, но основная механика та же: вариант calloc () и free ().

Так что да, после отправки [release release] объекта массивазначение счетчика достигает нуля, и объект немедленно отправляет -dealloc для себя, который вызывает free ().После этого любая попытка доступа к фрагменту памяти, занятому объектом, приведет к сбою (или, что еще хуже, если другой объект Obj-C будет размещен по тому же адресу, вы получите сбои в не связанных местах по всему коду).

Поскольку array2 - это просто еще один указатель на тот же, теперь освобожденный, кусок памяти, вы тоже ничего не можете с ним сделать.Лучшее, что вы можете сделать, это установить такие указатели в ноль, чтобы предотвратить случайный доступ к памяти, которой у вас больше нет.Obj-C достаточно умен, чтобы сделать сообщения, отправленные на nil (сообщения, отправленные на nil-указатели), no-ops.

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