Задача C Проблемы управления памятью - PullRequest
2 голосов
/ 09 июля 2010

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

Что я не получаю, так это когда речь идет о ivars & properties, сохранение в качестве свойства означает, что установщик освобождает старое значение и сохраняет новое:

property = newValue;
// retain
if (property != newValue)
{
   [property release];
    property = [newValue retain];
}

но я видел примеры, где они присваивают статические строки свойству сохранения, например,

self.stringProperty = @"something";
(some other code)
self.stringProperty = @"somethingElse";

Второй вызов set string должен вызывать release для статической строки, что недопустимо, почему не происходит сбой программы?

Кроме того, если объект объявлен со свойством retain, а затем ему присвоено что-то с помощью init, например,

@property(retain)someArray;

someArray = [[NSArray alloc] initWithArray:arbArray];

означает ли это, что someArray теперь имеет счет сохранения 2, но если он был создан с помощью

someArray = [NSArray arrayWithArray:arbArray];

счет сохранения только 1, потому что 2-ой - фабричный метод?

Ответы [ 3 ]

3 голосов
/ 09 июля 2010

Второй вызов set string должен вызывать release для статической строки, что недопустимо, почему не происходит сбой программы?

Вы можете передать release в константную строку, она просто ничего не сделает, поэтому эти строки кода верны.

означает ли это, что someArray теперь имеет счет сохранения 2, но если он был создан с ... счетчик хранения равен только 1, потому что 2-й является фабричным методом?

Ну, во-первых,

someArray = [[NSArray alloc] initWithArray:arbArray];

не использует методы, созданные @property, он просто напрямую обращается к ивару. Чтобы использовать методы свойств, вам нужно использовать self.someArray = ...;.

Но да,

[[NSArray alloc] initWithArray:arbArray]

возвращает объект с эффективным счетом сохранения 1, а

[NSArray arrayWithArray:arbArray]

возвращает объект с эффективным счетом сохранения 0, поэтому, если вы сделали , пропустите его через установщик «сохранения», созданный @property, у ивара будет эффективное количество хранения 2 и 1 соответственно.

0 голосов
/ 09 июля 2010

Второй вызов set string должен вызывать release для статической строки, что недопустимо, почему не происходит сбой программы?

Это не статическая строка, это постоянная строка. Однако это не имеет отношения к вопросу, но на самом деле вам разрешено отправлять -retain любому объекту Objective-C, производному от NSObject , за исключением NSAutoreleasePool. Если вы посмотрите на retainCount (немного капризный, но поскольку мы обсуждаем реализацию, хорошо) константы NSString, например

NSLog(@"retain count = %u", [@"foo" retainCount]);

вы, скорее всего, найдете действительно большое число (на самом деле UINT_MAX). Это сигнал времени выполнения, чтобы игнорировать вызовы на освобождение и сохранение.

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

означает ли это, что someArray теперь имеет счет сохранения 2, но если он был создан с помощью

Нет, поскольку вы не использовали свойство для присваивания нового массива, вы пошли прямо к ivar:

self.someArray = [[NSArray alloc] initWithArray:arbArray];

будет утечка.

self.someArray = [NSArray arrayWithArray:arbArray];

будет в порядке.

0 голосов
/ 09 июля 2010

Это больше, чем один вопрос, но в любом случае ...

Статические строки являются особыми случаями по ряду причин, одним из которых является то, что вы можете retain и release их в соответствии с вашим сердцем, без какого-либо эффекта.

Кроме того, свойства NString часто имеют семантику copy, а не retain, что в любом случае устранит этот вопрос, если он имеет значение. Но это не так.

Во втором случае присваивание retain свойства непосредственно из alloc (или copy или другого вызова с передачей прав собственности) является плохой практикой и будет иметь утечку, если вы не добавите соответствующий release впоследствии, или autorelease во время, например:

self.someArray = [[[NSArray alloc] initWithArray:arbArray] autorelease];

Но на самом деле нет никаких причин не использовать метод класса в этом конкретном случае.

...