2012-02-26 3 views
0

Я участвую в процессе обучения объективному c и программированию приложения iPad. Одна вещь, которую я продолжаю отключать, и перечитывать - это управление памятью. Я добираюсь туда ... медленно. Основные правила, например, для каждого alloc/retain, должны быть полезны release. Тем не менее, одна относительно простая вещь ускользает от меня, и мне интересно, если кто-то может объяснить ...Понимание управления памятью в ios

Возьмет следующий код ...

NSArray *myArray = [[NSArray alloc] init]; 
myArray = [someNSSet allObjects]; 

Это относительно прямое кодированием и потребует [myArray release] заявления.

Однако я продолжаю видеть примеры (и в самом деле, я использовал широко следующий «кратчайшие» ...

NSArray *myArray = (NSArray *)[someNSSet allObjects]; 

Как, насколько я понимаю, когда вы используете (NSString *) вам не нужен использовать [myArray release] заявление, но я не понимаю, почему.

Может кто-то можно объяснить?

ответ

1

В первой строке:

NSArray *myArray = [[NSArray alloc] init] 

некоторое количество памяти выделяется для массива (на самом деле в данном случае это не имеет смысла, так как размер массива равен 0. Имейте в виду, что NSArray неизменен!). Переменная myArray содержит адрес первого байта зарезервированной области памяти.

Теперь во второй строке вы меняете значение myArray, которое теперь укажет на первый байт области памяти, где хранится [someNSSet allObjects]. В этот момент вы больше не знаете, где массив хранит то, что вы создали в первой строке. И у вас есть утечка.

Линия:

NSArray *myArray = (NSArray *)[someNSSet allObjects]; 

правильно, так как вы не резервирует память в данный момент. Если вы не используете ARC, вы можете вызвать удержание, чтобы сохранить GC от ссылочного блока памяти. В противном случае вы можете получить BAD_EXEC, когда владелец объекта освободит его, и вы попытаетесь получить к нему доступ, например: [myArray objectAtIndex: 0]

2
NSArray *myArray = [[NSArray alloc] init]; 
myArray = [someNSSet allObjects]; 

этот код протечки myArray, потому что вы теряете ссылку на NSArray, которую вы выделили на первой строке; вам здесь не нужно alloc, потому что на второй строке вы назначаете новое значение myArray.

NSArray *myArray = (NSArray *)[someNSSet allObjects]; 

и этот пример кода, это прекрасно, вы присваиваете результат [someNSSet allObjects] для myArray указателя и вы не владеете возвращаемое значение, так что вам не нужно заботиться об освобождении его.

Рассмотрите возможность использования ARC (Automatic Retain Counting) для вашего проекта. С ARC компилятор позаботится о сохранении счета, поэтому вам не нужно, на самом деле не разрешено. Существует рефакторинг, который преобразует текущий проект.

+0

Почему я не владею возвращенным значением. Кто/что делает? –

+0

@BenThompson: Когда вы создаете объект (new или alloc, copy или mutableCopy), он имеет значение удержания 1 и вы его обладаете. Когда вы отправляете объекту сообщение сохранения, его количество удержания увеличивается на 1, и вы тоже владеете им. Вам нужно только освободить объекты, которыми вы владеете. –

+1

@Ben: Скорее всего, пул авторасчетов является владельцем объекта, возвращаемого из 'allObjects'. Другая возможность - это заданный объект, но это действительно произойдет только в том случае, если набор просто выставляет объект, который уже принадлежит, вместо создания нового массива. Однако, за исключением понимания того, что происходит на заднем плане, вы не должны беспокоиться о том, кто владеет вещами. Либо вы это делаете, либо нет, и это все, что вам нужно учитывать. –

2

Как вы сказали, есть утечка в первом введенном вами коде. так что вы должны добавить релиз:

NSArray *myArray = [[NSArray alloc] init]; 
[myArray release]; 
myArray = [someNSSet allObjects]; 

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

Что касается второго примера, вы получили массив, хотя метод, который не начинается с одной из трех слов (alloc, new или copy), так что вы не являетесь владельцем объекта, и вы не несет ответственности освободить его. Фактически, массив, который вы получили, является автореализованным объектом, а это означает, что, хотя его счет сохранения в настоящее время равен 1, он будет автоматически освобожден, когда что-то, называемое пулом авторезистов, будет истощено.

См. Также ссылку Memory Management Rules.

+0

может быть лучше инвертировать строку 2 с помощью строки 3 в вашем ответе (или использовать авторекламу вместо выпуска) – meronix

+0

'release' в строке 2 состоит в балансировке' alloc' в строке 2, так что старое значение 'myArray' не течет. Нам нужно сделать это, прежде чем назначать новое значение 'myArray'. – sch

+0

да, конечно, но если вы отпустите его, в строке 3 myArray больше не существует, он не будет больше выделен и может дать вам ошибку, и вы не сможете его использовать. вы должны балансировать выделение с выпуском и использовать свои объекты между этими двумя строками. или нет? – meronix

Смежные вопросы