Как работает пул автозапуска NSAutoreleasePool?

objective-c memory-management nsautoreleasepool foundationkit

85777 просмотра

7 ответа

Насколько я понимаю, все, что создано с помощью 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];
}
Автор: James Sumners Источник Размещён: 11.11.2019 01:43

Ответы (7)


67 плюса

Решение

Да, ваш второй фрагмент кода полностью действителен.

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

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

Автор: kperryua Размещён: 15.09.2008 06:36

37 плюса

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

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

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

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

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

Автор: mmalc Размещён: 08.10.2008 01:14

17 плюса

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

Я хотел бы предложить более краткий способ использования пула автоматического выпуска, который работает во всех средах (подсчет ссылок, GC, ARC), а также избегает путаницы утечки / выпуска:

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

В приведенном выше примере обратите внимание на блок @autoreleasepool . Это задокументировано здесь .

Автор: Neovibrant Размещён: 03.11.2011 07:02

7 плюса

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

Автор: kperryua Размещён: 15.09.2008 11:55

0 плюса

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

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

Автор: Gagan_iOS Размещён: 20.02.2014 01:27

0 плюса

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

Автор: Hardik Mamtora Размещён: 27.06.2014 01:07

-2 плюса

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

сливной

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

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

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

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

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

Автор: Loren Segal Размещён: 15.09.2008 06:39
32x32