Понимание подсчета ссылок с Какао и Objective-C

Согласно IBM - это не для классов или методов.

http://www.ibm.com/developerworks/java/library/j-jtp04223.html

122
задан Peter Mortensen 6 April 2011 в 09:33
поделиться

14 ответов

Давайте запустимся с retain и release; autorelease действительно просто особый случай, после того как Вы понимаете фундаментальные понятия.

В Какао, каждый объект отслеживает то, сколько раз на это ссылаются (а именно, NSObject, базовый класс реализует это). Путем вызова retain на объекте, Вы говорите этому, что хотите к его подсчету ссылок одним. Путем вызова release, Вы говорите объекту, что отпускаете его, и его подсчет ссылок постепенно уменьшается. Если, после вызова release, подсчет ссылок является теперь нулем, то память того объекта освобождена системой.

основной способ, которым это отличается от [1 110] и free, состоит в том, что любой данный объект не должен волноваться о других частях системного катастрофического отказа, потому что Вы освободили память, которую они использовали. Принятие всех манипулирует и сохраняет/выпускает согласно правилам, когда одна часть кода сохранит и затем выпускает объект, любая другая часть кода, также ссылающегося на объект, будет незатронута.

то, Что может иногда сбивать с толку, знает обстоятельства, при которых необходимо звонить retain и release. Мое общее эмпирическое правило - то, что, если я хочу держаться за объект в течение некоторого отрезка времени (если это - членская переменная в классе, например), затем я должен удостовериться, что подсчет ссылок объекта знает обо мне. Как описано выше, подсчет ссылок объекта увеличен путем вызова retain. Условно, это также увеличено (набор к 1, действительно), когда объект создается с "init" методом. В любом из этих случаев это - моя обязанность звонить release на объекте, когда я сделан с ним. Если я не сделаю, то будет утечка памяти.

Пример создания объекта:

NSString* s = [[NSString alloc] init];  // Ref count is 1
[s retain];                             // Ref count is 2 - silly
                                        //   to do this after init
[s release];                            // Ref count is back to 1
[s release];                            // Ref count is 0, object is freed

Теперь для [1 116]. Автовыпуск используется в качестве удобного (и иногда необходимый) способ сказать системе освобождать этот объект скоро. С точки зрения инфраструктуры, когда autorelease назван, текущий поток NSAutoreleasePool предупрежден вызова. NSAutoreleasePool теперь знает, что, после того как это получает возможность (после текущего повторения цикла событий), это может звонить release на объекте. С нашей точки зрения как программисты это заботится о вызове release для нас, таким образом, мы не имеем к (и на самом деле, мы не были должны).

то, Что важно для примечания, - то, что (снова, условно) все создание объекта методы класса возвращают автовыпущенный объект. Например, в следующем примере, переменная "s" имеет подсчет ссылок 1, но после того, как цикл событий завершается, это будет уничтожено.

NSString* s = [NSString stringWithString:@"Hello World"];

, Если бы Вы хотите зависнуть на ту строку, необходимо было бы звонить retain явно, и затем явно release она, когда Вы сделаны.

Считают следующее (очень изобретенным) битом кода, и Вы будете видеть ситуацию, где autorelease требуется:

- (NSString*)createHelloWorldString
{
    NSString* s = [[NSString alloc] initWithString:@"Hello World"];

    // Now what?  We want to return s, but we've upped its reference count.
    // The caller shouldn't be responsible for releasing it, since we're the
    // ones that created it.  If we call release, however, the reference 
    // count will hit zero and bad memory will be returned to the caller.  
    // The answer is to call autorelease before returning the string.  By 
    // explicitly calling autorelease, we pass the responsibility for
    // releasing the string on to the thread's NSAutoreleasePool, which will
    // happen at some later time.  The consequence is that the returned string 
    // will still be valid for the caller of this function.
    return [s autorelease];
}

я понимаю, что все это немного сбивает с толку - в какой-то момент, тем не менее, это нажмет. Вот несколько ссылок для получения Вас движение:

148
ответ дан Matt Dillard 6 April 2011 в 09:33
поделиться

Ответ NilObject является хорошим началом. Вот некоторая дополнительная информация, имеющая отношение к ручному управлению памятью ( требуется на iPhone).

, Если Вы лично alloc/init объект, это идет с подсчетом ссылок 1. Вы ответственны за чистку после него, когда это больше не необходимо, или путем вызова [foo release] или [foo autorelease]. выпуск очищает его сразу же, тогда как автовыпуск добавляет объект к пулу автовыпуска, который автоматически выпустит его в более позднее время.

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

, Если Вы получаете объект, где Вы не назвали alloc/init для получения его - например:

foo = [NSString stringWithString:@"hello"];

, но Вы хотите держаться за этот объект, необходимо звонить [нечто сохраняют]. Иначе возможно, что это доберется autoreleased, и Вы будете держаться за нулевую ссылку (как это было бы в вышеупомянутом stringWithString пример ). Когда Вам больше не будет нужен он, звоните [foo release].

4
ответ дан Sangram Shivankar 6 April 2011 в 09:33
поделиться

Joshua (#6591) - Материал Сборки "мусора" в Mac OS X 10.5 кажется довольно прохладным, но не доступен для iPhone (или если Вы хотите, чтобы Ваше приложение работало на пред10.5 версиях Mac OS X).

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

6
ответ дан Matt Sheppard 6 April 2011 в 09:33
поделиться

Использование Objective C Подсчет ссылок , что означает каждый Объект, имеет подсчет ссылок. Когда объект создается, он имеет подсчет ссылок "1". Просто разговор, когда объект упомянут (т.е., сохраненный где-нибудь), он "сохраняется", что означает, что его подсчет ссылок увеличен одним. Когда объект больше не необходим, он "выпущен", что означает, что его подсчет ссылок уменьшен одним.

, Когда подсчет ссылок объекта 0, объект освобожден. Это - основной подсчет ссылок.

Для некоторых языков, ссылки автоматически увеличены и уменьшены, но цель-c не является одним из тех языков. Таким образом программист ответственен за сохранение и выпуск.

А типичный способ записать метод:

id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;

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

, Когда объект отправит сообщение "автовыпуска" в него, объект будет искать любые пулы автовыпуска, находящиеся на стеке для этого текущего потока. Это добавит объект к списку как объект отправить сообщение "выпуска" в в какой-то момент в будущем, которое является обычно, когда сам пул выпущен.

Взятие кода выше, можно переписать его, чтобы быть короче и легче читать путем высказывания:

id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;

, поскольку объект автовыпущен, мы больше не должны явно называть "выпуск" на нем. Это вызвано тем, что мы знаем, что некоторый пул автовыпуска сделает это для нас позже.

, Надо надеяться, это помогает. Статья Wikipedia довольно хороша о подсчете ссылок. Больше информации приблизительно пулы автовыпуска может быть найдено здесь . Также обратите внимание, что, если Вы создаете для Mac OS X 10.5 и позже, можно сказать, что XCode для создания с включенной сборкой "мусора", позволяя Вам полностью проигнорировать сохраняет/выпускает/автовыпускает.

6
ответ дан NilObject 6 April 2011 в 09:33
поделиться

Если Вы - написание кода для рабочего стола, и можно быть нацелены на Mac OS X 10.5, необходимо, по крайней мере, изучить использование сборки "мусора" Objective C. Это действительно упростит большую часть Вашей разработки — вот почему, Apple приложила все усилия к созданию его во-первых и тому, чтобы заставлять его работать хорошо.

Что касается управления памятью управляет если не использованием GC:

  • при создании нового объекта с помощью +alloc/+allocWithZone:, +new, -copy или -mutableCopy или если Вы -retain объект, Вы берете владение его и должны удостовериться, он отправляется -release.
  • при получении объекта каким-либо другим способом Вы не владелец его и если не гарантируют, что он отправляется -release.
  • , Если Вы хотите удостовериться, объект отправляется -release, можно или отправить это сами, или можно отправить объект -autorelease и ток , пул автовыпуска отправит его -release (однажды на полученный -autorelease), когда пул будет истощен.

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

8
ответ дан Chris Hanson 6 April 2011 в 09:33
поделиться

Матовый Диллард записал :

возврат [[s автовыпуск] выпуск];

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

5
ответ дан Community 6 April 2011 в 09:33
поделиться

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

  1. , Если функция, которая возвращает объект, имеет alloc, create или copy на его имя затем, объект является Вашим. Необходимо звонить [object release], когда Вы закончены с ним. Или CFRelease(object), если это - объект Базовой Основы.

  2. , Если это НЕ имеет одного из этих слов на его имя затем, объект принадлежит кому-то еще. Необходимо звонить [object retain], если Вы хотите сохранить объект после конца Вашей функции.

Вы были бы хорошо обслужены, чтобы также следовать этой конвенции в функциях, которые Вы создаете сами.

(Педанты: Да, существует, к сожалению, несколько вызовов API, которые являются исключениями к этим правилам, но они редки).

10
ответ дан Unheilig 6 April 2011 в 09:33
поделиться

Большая хорошая информация о cocoadev также:

1
ответ дан charles 6 April 2011 в 09:33
поделиться

Как всегда, когда люди начинают пытаться перефразировать ссылочный материал, они почти неизменно получают что-то не так или предоставляют неполное описание.

Apple предоставляет полное описание системы управления памятью Какао в Руководство по программированию управления памятью для Какао , в конце которого существует краткая, но точная сводка Правила .

управления памятью
6
ответ дан mmalc 6 April 2011 в 09:33
поделиться

Ответы выше дают ясные повторные заявления того, что говорит документация; проблемой, с которой сталкиваются самые новые люди, являются недокументированные случаи. Например:

  • Автовыпуск : в документах говорится, что это инициирует выпуск "в какой-то момент в будущем". КОГДА?! В основном можно рассчитывать на объект, являющийся вокруг, пока Вы не выходите из своего кода назад в цикл системного события. Система МОЖЕТ выпустить объект любое время после цикла текущего события. (Я думаю, что Matt сказал это, ранее.)

  • Статические строки : NSString *foo = @"bar"; - необходимо ли сохранить или выпустить ли это? Нет. Как насчет [1 118]

    -(void)getBar {
        return @"bar";
    }
    

    ...

    NSString *foo = [self getBar]; // still no need to retain or release
    
  • Правило Создания: при создании его Вы владеете им и, как ожидают, выпустите его.

В целом, способ, которым испорчены новые программисты Cocoa, не понимая, какие стандартные программы возвращают объект с retainCount > 0.

Вот отрывок от Очень Простые Правила Для управления памятью В Какао :

правила количества Хранения

  • В данном блоке, использовании - копия, - который сохраняет выделение и - должна равняться использованию - выпуск и-autorelease.
  • Объекты, созданные с помощью конструкторов удобства (например, stringWithString NSString), считают автовыпущенными.
  • Реализация-dealloc метод для выпуска instancevariables Вы владеете

, 1-й маркер говорит: если Вы звонили alloc (или new fooCopy), Вам нужно к разъединению вызова на том объекте.

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

3-е должно быть очевидным.

2
ответ дан Jason Plank 6 April 2011 в 09:33
поделиться

Существует свободный скринкаст, доступный из iDeveloperTV Сети

управление памятью в Objective C

4
ответ дан Abizern 6 April 2011 в 09:33
поделиться

Мой обычный набор статей управления памятью Какао:

управление памятью какао

5
ответ дан NANNAV 6 April 2011 в 09:33
поделиться

Я не добавлю к определенному из, сохраняют/выпускают кроме Вас, мог бы хотеть думать об отбрасывании 50$ и получении книги Hillegass, но я настоятельно рекомендую войти в использование инструментов Instruments очень рано в разработке Вашего приложения (даже Ваш первый!). Для этого Выполнение-> Запускается с инструментов производительности. Я запустил бы с Утечек, который является только одним из многих доступных инструментов, но поможет показать Вам, когда Вы имеете, забыл выпускать. Это вышло из укрощения, с каким количеством информации Вы будете представлены. Но проверьте это учебное руководство для подъема и движение быстро:
УЧЕБНОЕ РУКОВОДСТВО ПО КАКАО: ФИКСАЦИЯ УТЕЧЕК ПАМЯТИ С ИНСТРУМЕНТАМИ

На самом деле попытка к сила утечки могли бы быть лучшим способом, в свою очередь, учась, как предотвратить их! Удача ;)

6
ответ дан Rob 6 April 2011 в 09:33
поделиться

Как уже упоминали несколько человек, Apple Введение в управление памятью , безусловно, является лучшим местом для начала.

Одна полезная ссылка, о которой я еще не упоминал, - это Практическое управление памятью . Вы найдете его в середине документации Apple, если прочитаете их, но на него стоит прямая ссылка. Это блестящее резюме правил управления памятью с примерами и типичными ошибками (в основном то, что другие ответы здесь пытаются объяснить, но не так хорошо).

0
ответ дан 24 November 2019 в 01:24
поделиться