Нужно уточнить в управлении памятью iPhone - PullRequest
0 голосов
/ 15 февраля 2011

Мне нужно немного разъяснений в управлении памятью iPhone.

Вот пример для сеттеров;
1).

-(void)setValue:(NSString*)input{
[value autorelease];
value = [input retain];
}

В этом примере, почему мы должны использовать авто-релиз? Можем ли мы использовать как следующим образом?


if(value)
[value release];
value = [input retain];

В первом примере, Почему мы не должны освобождать память для input
2). Если я использую следующее утверждение; каков счет удержания для value

NSString *value;
value = @"welcome";

После вышеприведенного утверждения я просто пытаюсь установить еще одно значение. Тогда что будет?

eg:
value = @"For testing";

3). В чем разница между 2) и 3)?

NSString *value;
value = [input1 retain];
...
...
value = [input2 retain];// Now what is the retain count for <b>value</b>

4). Если я использую следующее утверждение, почему приложение получает сбой?


NSString *value = [[[NSString alloc] init] autorelease];
...
...

Заранее спасибо ..

Ответы [ 5 ]

2 голосов
/ 15 февраля 2011

Если «input» - это тот же объект, что и «value», то вызов [value release] может освободить объект. Таким образом, вы должны сохранить новое входное значение, освободить старое значение, а затем присвоить новое значение для ivar:

[input retain];
[value release];
value = input;

После каждого из 2) и 3) значение NSString * указывает на литеральный объект NSString, счетчик сохранения будет равен 1 в каждом случае, и выпуск его, вероятно, не очень хорошая идея

После этого кода:

value = [input2 retain];

значение является псевдонимом объекта input2. Необходимо понять, что объекты имеют счетчики, переменные - нет.

Что касается вашего последнего случая,

NSString *value = [[[NSString alloc] init] autorelease];

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

0 голосов
/ 15 февраля 2011

(при условии, что вы работаете в среде без gc)

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

2), технически литералы NSString действительны в течение всей жизни вашей программы.то есть: while (1) [@"why won't i die?" release]; дает бесконечный цикл.

3) с явным сохранением, alloc + init, new и copy, вы должны уравновесить счет сохранения, используя release или autorelease.поскольку вы не опубликовали значение1, статический анализ может (правильно) определить это как утечку.поскольку строковые константы никогда не умирают, эти два несопоставимы в этом отношении.

4) в этом нет ничего плохого.проблема лежит в другом месте вашей программы.либо вы присваиваете его ивару без сохранения, либо выпускаете его позже.

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

и, наконец, проверьте на утечки и запустите с включенными NSZombies.

0 голосов
/ 15 февраля 2011

Я обычно пишу мои сеттеры как

- (void)setValue:(NString *)input {
    if (value != input) {
        [value release];
        value = [input retain];
    }
}

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


Однако рекомендуется копировать строки вместоих:)

0 голосов
/ 15 февраля 2011

1) Вам нужно будет выполнить авто-релиз из-за следующего: Когда вход является тем же объектом, что и значение, и вы сбрасываете значение, его счетчик удержания достигнет нуля и будет освобожден, прежде чем вы сможете снова сохранить его через вход. Вы можете сделать это с помощью команды retain, но вы должны изменить свой код:

-(void)setValue:(NSString*)input{
   if (value != input) {
      [value autorelease];
      value = [input retain];
   }
}

2) Я верю, что @ "Текст" будет рассматриваться как константа. Когда вам нужен объект, для которого вы не хотите никакого управления памятью с использованием:

NSString *value = [NSString stringWithString:@"Text"];

Это вернет автоматически выпущенный объект.

3) В этом примере речь идет не о счетчике сохранения значения, а о счетчике хранения обоих объектов, на которые ссылается значение one. Если вы не отпустите input1 до выхода из этого метода, у вас будет проблема с управлением памятью.

4) Это утверждение должно работать. Нет смысла спорить. Вы скорее используете [NSString string].

Примечание: Для управления памятью: когда вы используете alloc new или copy , вы также должны использовать release или autorelease для того же объекта в тот же объем.

0 голосов
/ 15 февраля 2011

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

object.value = object.value;

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

...