objective c management Как работает пул автозаполнения NSAutoreleasePool?




ios autorelease (8)

NSAutoreleasePool: утечка против выпуска

Поскольку функция drain и release , по-видимому, вызывает путаницу, это может быть полезно разъяснить здесь (хотя это описано в документации ...).

Строго говоря, с точки зрения большой картины drain не эквивалентна release :

В среде с подсчетом ссылок drain выполняет те же операции, что и release , поэтому эти два эквивалента эквивалентны. Чтобы подчеркнуть, это означает, что вы не просачиваете пул, если используете drain а не release .

В среде сбора мусора release - это не-op. Таким образом, это не имеет никакого эффекта. drain , с другой стороны, содержит подсказку сборщику о том, что он должен «собирать при необходимости». Таким образом, в среде сбора мусора использование drain помогает собирать систему баланса.

Насколько я понимаю, все, что создано с помощью alloc , new или copy, должно быть выпущено вручную. Например:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

Мой вопрос, однако, не так ли это справедливо ?:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}

Answer #1

Да и нет. Вы в конечном итоге освободите строку памяти, но «пропустите» объект NSAutoreleasePool в память, используя денек вместо выпуска, если вы запускаете это под средой сбора собранных мусора (не управляемых памятью). Эта «утечка» просто делает экземпляр NSAutoreleasePool «недоступным», как любой другой объект без сильных указателей под GC, и объект будет очищен в следующий раз, когда GC запускается, что вполне может быть непосредственно после вызова -drain :

истощать

В среде сбора мусора запускается сбор мусора, если память, выделенная с момента последней коллекции, больше, чем текущий порог; иначе ведет себя как релиз. ... В среде сбора мусора этот метод в конечном итоге вызывает objc_collect_if_needed .

В противном случае это похоже на то, как -release ведет себя не-GC, да. Как утверждали другие, -release - это не-op под GC, поэтому единственный способ убедиться, что пул функционирует должным образом под GC, проходит через -drain , а -drain в не-GC работает точно так же, как -release under non-GC, и, возможно, более четко передает свои функциональные возможности.

Я должен указать, что ваше утверждение «все, что называется с новым, alloc или init» не должно включать «init» (но должно включать «copy»), потому что «init» не выделяет память, он только устанавливает объект (конструктор мода). Если вы получили объект alloc'd, и ваша функция только называется init как таковая, вы бы не выпустили его:

- (void)func:(NSObject*)allocd_but_not_init
{
    [allocd_but_not_init init];
}

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


Answer #2

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


Answer #3

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


Answer #4

Да, ваш второй код снипп отлично.

Каждый раз, когда -autorelease отправляется на объект, он добавляется к самому большому пулу автообновлений. Когда пул сливается, он просто отправляет -возбуждает все объекты в пуле.

Пулы Autorelease - это просто удобство, которое позволяет отложить отправку-освобождение до «позже». То, что «позже» может произойти в нескольких местах, но наиболее распространенное в приложениях GUI Cocoa находится в конце текущего цикла цикла цикла.


Answer #5

То, что я прочитал от Apple: «В конце блока пула авторезистов объекты, которые получили сообщение автозапуска в блоке, отправляют сообщение о выпуске - объект получает сообщение о выпуске для каждого момента, когда ему было отправлено сообщение автозапуска в блоке. "

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html


Answer #6

Нет, ты ошибаешься. В документации четко указано, что при не-GC, -drain эквивалентно -release, то есть NSAutoreleasePool не будет просачиваться.


Answer #7

Я нашел, что эта ссылка дала лучшее объяснение того, когда и как использовать NSAutoReleasePool: AutoReleasePool







foundationkit