Насколько я понимаю, все, что создано с помощью 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];
}
objective-c
memory-management
nsautoreleasepool
foundationkit
Джеймс Самнерс
источник
источник
an object
должно бытьan object that is a subclass of NSObject or NSProxy and doesn't override -autorelease
.NSAutoreleasePool: слив против выпуска
Поскольку функция
drain
и,release
похоже, вызывает путаницу, возможно, стоит уточнить здесь (хотя это описано в документации ...).Строго говоря, с точки зрения общей картины
drain
это не эквивалентноrelease
:В среде с подсчетом ссылок
drain
он выполняет те же операции, что иrelease
, поэтому в этом смысле они эквивалентны. Подчеркнем: это означает, что вы не утекаете из пула, если используетеdrain
вместоrelease
.В среде со сборкой мусора
release
это не работает. Таким образом, это не имеет никакого эффекта.drain
, с другой стороны, содержит подсказку сборщику, что он должен «собирать при необходимости». Таким образом, в среде со сборкой мусора использованиеdrain
помогает сбалансировать сборку системы.источник
NSAutoreleasePool
. Это потому, что пулы работают как стек. Создание экземпляра пула подталкивает этот пул к вершине стека пула автоматического освобождения потоков.-release
заставляет этот пул выталкиваться из стека И любых пулов, которые были помещены поверх него, но по какой-либо причине не были вытолкнуты.Как уже отмечалось, ваш второй фрагмент кода верен.
Я хотел бы предложить более лаконичный способ использования пула автозапуска, который работает во всех средах (подсчет ссылок, GC, ARC), а также позволяет избежать путаницы слива / выпуска:
Обратите внимание на блок @autoreleasepool в приведенном выше примере . Это описано здесь .
источник
@autoreleasepool
блок с ARC.Нет, вы ошибаетесь. В документации четко указано, что под без GC, -drain эквивалентен -release, что означает, что NSAutoreleasePool не будет утекать .
источник
NSAutoreleasePool
: developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…Что я прочитал от Apple: «В конце блока пула автозапуска объектам, которые получили сообщение автозапуска в блоке, отправляется сообщение об освобождении - объект получает сообщение об освобождении каждый раз, когда он отправляет сообщение об автозапуске в блоке. "
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html
источник
отправка автозапуска вместо освобождения объекту продлевает время жизни этого объекта, по крайней мере, до тех пор, пока сам пул не будет истощен (это может быть дольше, если объект впоследствии будет сохранен). Объект может быть помещен в один и тот же пул несколько раз, и в этом случае он будет получать сообщение об освобождении каждый раз, когда он был помещен в пул.
источник
Да и нет. В конечном итоге вы бы освободили строковую память, но «просочили» объект NSAutoreleasePool в память, используя слив вместо выпуска, если бы вы запускали это в среде со сборкой мусора (не управляемой памятью). Эта «утечка» просто делает экземпляр NSAutoreleasePool «недоступным», как и любой другой объект без сильных указателей в GC, и этот объект будет очищен при следующем запуске GC, что вполне может произойти сразу после вызова
-drain
:В остальном это похоже на то, как
-release
ведет себя без GC, да. Как утверждали другие,-release
это не работает под GC, поэтому единственный способ убедиться, что пул функционирует должным образом под GC, - это сквозной-drain
, а-drain
под не-GC работает точно так же, как и-release
под не-GC, и, возможно, передает свои функции более четко, как хорошо.Я должен указать, что ваше утверждение «все, что вызывается с помощью new, alloc или init» не должно включать «init» (но должно включать «copy»), потому что «init» не выделяет память, а только устанавливает объект (конструктор мода). Если вы получили объект alloc'd, а ваша функция вызывала только init как таковую, вы бы не выпустили ее:
Это не потребляет больше памяти, чем вы уже начали (при условии, что init не создает экземпляры объектов, но вы в любом случае не несете ответственности за них).
источник
-[NSAutoreleasePool release]
в среде со сборкой мусора это не работает.-[NSAutoreleasePool drain]
работает как в средах с подсчетом ссылок, так и со сборкой мусора.