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

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

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];
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
95
0
86 605
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

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

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

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

где конец текущего цикла цикла выполнения, если у меня нет цикла?

Thanks 13.04.2009 11:23

Разве «самый внешний» не должен быть «самым внутренним»?

Mike Weller 08.06.2010 19:33

an object должен быть an object that is a subclass of NSObject or NSProxy and doesn't override -autorelease.

user142019 23.04.2011 15:18

Обновлено: изменено самое внешнее на самое внутреннее.

chakrit 29.12.2011 09:30

Важно: если вы используете автоматический подсчет ссылок (ARC), вы не можете использовать пулы с автоматическим выпуском напрямую. Вместо этого вы используете блоки @autoreleasepool. От developer.apple.com/library/mac/#documentation/Cocoa/Referen‌ ce /…

Md Mahbubur Rahman 28.03.2013 10:11

@ Спасибо Цикл выполнения - это не цикл. Это не языковая конструкция вроде for или while. Это скорее механизм диспетчеризации, который управляет различными состояниями выполнения и событиями в потоке.

user529758 07.07.2013 11:44

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

drain

In a garbage collected environment, triggers garbage collection if memory allocated since last collection is greater than the current threshold; otherwise behaves as release. ... In a garbage-collected environment, this method ultimately calls 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 не создает экземпляры объектов, но вы в любом случае не несете ответственности за них).

Мне неудобно оставлять этот ответ принятым, если ваша информация о сливе не совсем верна. См. Обновление developer.apple.com/documentation/Cocoa/Reference/Foundation‌ /…, и я приму его повторно.

James Sumners 16.09.2008 08:16

Что неточного в ответе? В среде со сборкой мусора (как указано) слив не удаляет пул AutoReleasePool, поэтому вы используете буду утечки памяти, если вы не использовали release. Цитата, которую я перечислил, была прямо из уст лошади, документы на сливе.

Loren Segal 17.09.2008 23:27

Лорен: В GC, - [NSAutoreleasePool Drain] вызовет сбор. -retain, -release и -autorelease игнорируются сборщиком; вот почему -drain используется в пулах автозапуска под GC.

Chris Hanson 23.09.2008 12:04

В документации по «сливу»: в среде с управляемой памятью это ведет себя так же, как вызов release. Таким образом, у вас будет утечка памяти нет, если вы используете «слив» вместо выпуска.

mmalc 08.10.2008 05:17

-[NSAutoreleasePool release] в среде со сборкой мусора не работает. -[NSAutoreleasePool drain] работает как в средах с подсчетом ссылок, так и со сборкой мусора.

Jonathan Sterling 08.12.2009 04:02

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

Мне было интересно, почему Xcode генерирует код с -drain, если это так. Я использовал -drain, потому что думал, что он эквивалентен -release на основе кода, сгенерированного Xcode.

James Sumners 16.09.2008 04:01

«Утечка» NSAutoreleasePool принципиально невозможно: developer.apple.com/mac/library/documentation/Cocoa/Conceptu‌ al /…

johne 06.09.2009 07:18

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

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

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

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

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

«Утечка» NSAutoreleasePool принципиально невозможна. Это потому, что пулы работают как стек. Создание пула подталкивает этот пул к вершине стека пула автоматического высвобождения потоков. -release заставляет этот пул выталкивать из стека И любые пулы, которые были помещены поверх него, но по какой-либо причине не были вытолкнуты.

johne 06.09.2009 07:12

Каким образом это относится к тому, что я написал?

mmalc 26.01.2010 19:19

Мне нравится, как он нашел время, чтобы выделить И. ЩЕЛЧОК!

Billy Gray 18.11.2010 22:42

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

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

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

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

Обратите внимание, что автоматический выпуск не разрешен с ARC.

dmirkitanov 27.06.2012 01:25

Чтобы уточнить, нужно использовать блок @autoreleasepool с ARC.

Simon 30.06.2012 00:17

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

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

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

Другие вопросы по теме