Как свойства управления памятью влияют на ячейки массива? - PullRequest
3 голосов
/ 24 апреля 2011

В моей книге по разработке для iPhone я вижу странные примеры кодирования в отношении того, что делает массив, когда объекты добавляются в массив и когда освобождается весь массив. Один пример кода имеет следующие свойства массива экземпляра:

@property (nonatomic, retain) NSMutableArray* myArray;

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

SomeObject* someObject = [[SomeObject alloc] init];
[self.myArray addObject:someObject];
[someObject release];

Автор также освобождает указатель на массив без предварительного прохождения каждой ячейки массива и освобождения отдельных объектов. Это утечка памяти, если за кадром каждой ячейке не отправлено сообщение release ;.

- (void)viewDidUnload {
    self.myArray = nil;
    [super viewDidUnload];
}

Ответы [ 4 ]

2 голосов
/ 24 апреля 2011

В отличие от C или C ++, где вы постоянно беспокоитесь о том, удалять ли объект или нет, так как боитесь, что он все еще используется где-то еще, Objective-C (точнее, это вообще-то Cocoa SDK) использует механизм подсчета ссылок или владение.

Вы, возможно, уже знаете, как это работает, но вам также необходимо знать, что в Какао, если объекту A нужно использовать другой объект B, он должен владеть (т.е. сохранять) его. Этот объект A не должен полагаться на какой-либо другой объект C, уже сохранивший B, потому что он не может знать, когда C освобождает его. Так что в вашем случае, поскольку NSArray должен использовать все объекты, добавленные к нему последними в течение своего времени жизни, ему необходимо сохранить все объекты. И из-за этого, когда массив де-распределен, он должен освободить их.

Эта концепция «вам нужно сохранить то, что вы хотите использовать последним», очень важна, когда вы имеете дело с большим количеством объектов.

2 голосов
/ 24 апреля 2011

Если, за кадром, ячейка массива сохраняет объект при добавлении.

Да, это происходит.

... если за кулисами каждой ячейке не отправлено сообщение об освобождении.

Это также происходит.

Вы ответили на свой вопрос.

Вот цитата из Темы программирования коллекций :

А когда вы добавляете объект в NSMutableArray объект, объект не копируется, (если вы не передаете YES как аргумент initWithArray: copyItems :). Скорее Объект добавляется непосредственно в массив. В управляемой среде памяти объект получает сообщение сохранения, когда это добавлено; в мусор собрал среда, это сильно ссылки. Когда массив освобождается в управляемой памяти среда, каждый элемент отправляется отпустить сообщение.

1 голос
/ 24 апреля 2011
  • Вы правы в первом пункте. Когда объект добавляется в массив, массив сохраняет объект. Таким образом, для объекта, который был ранее сохранен, необходимо освободить его после добавления его в массив, иначе вы можете получить утечку памяти.

  • Аналогично, когда объект удален из массива, массив освобождает объект. Итак, если вы хотите сохранить его, вам нужно сохранить его.

  • Когда массив освобождается, как вы предположил, что массив освободит все объекты, которые он содержит. Таким образом, выпуск каждого объекта по отдельности не обязательно и, по сути, будет поднять исключение.

  • Наконец, относительно строки кода в -viewDidUnload, который вы цитировали:

    self.myArray = nil;
    

Это правильно работает в отношении управления памятью, если свойство myArray было синтезировано следующим образом:

@synthesize myArray;

Синтезирование создает сеттер, который эффективно выполняет следующие действия:

- (void)setMyArray(NSMutableArray *)anArray
{
    if (![myArray isEqual:anArray]) {
        [myArray release];
        myArray = anArray;
        [myArray retain];
    }
}

Таким образом, при вызове вышеприведенный установщик сначала освобождает старый массив (при условии, что он не совпадает с новым массивом). Затем он сохраняет новый массив, который в данном случае равен нулю. Обратите внимание, что сохранение nil просто ничего не сделает и не вызовет ошибку.

Конечно, если вы не синтезируете свойство myArray или переопределите установщик, у вас будут проблемы с памятью, если только вы не освободите старое значение и не сохраните новое в своем установщике.

1 голос
/ 24 апреля 2011

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

Учитывая это, вы были правы, предполагая, что NSArray сохраняет объект при добавлении в коллекцию, поскольку он все еще может попытаться получить к нему доступ позже.

Вы можете проверить Руководство по программированию управления памятью

Когда вы добавляете объект в коллекцию, такую ​​как массив, словарь или набор, коллекция становится его владельцем.

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW3

или темы программирования коллекций для получения более подробной информации

... В среде управляемой памяти объект получает сообщение сохранения при добавлении.

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Arrays.html#//apple_ref/doc/uid/20000132-SW1

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