Как NSAutoreleasePool autorelease пул работает?
Как я понимаю, все, что создается с помощью alloc,новая или скопировать должен быть освобожден вручную. Например:
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];
}
9 ответов:
Да, ваш второй фрагмент кода вполне допустим.
каждый раз-autorelease направляется на объект, он добавляется в самый внутренний autorelease пул. Когда пул сливается, он просто отправляет-release всем объектам в пуле.
Autorelease бассейны являются просто удобство, что позволяет отложить выпуск до "позже". Это "позже" может произойти в нескольких местах, но наиболее распространенным в приложениях Cocoa GUI является конец текущего цикла запуска ездить на велосипеде.
NSAutoreleasePool: слив против выпуска
так как функция
drainиreleaseКажется, вызывает путаницу, это может быть стоит уточнить здесь (хотя это описано в документация...).строго говоря, с точки зрения большой картины
drainи не эквивалентноrelease:в среде с подсчетом ссылок,
drainвыполняет те же операции, что иrelease, Так что два в этом смысле эквивалентны. Чтобы подчеркнуть, это означает, что вы делаете не утечка в бассейн, если вы используетеdrain, а неrelease.в мусорной среде,
releaseнет. Таким образом, это не имеет никакого эффекта.drain, с другой стороны, содержит подсказку коллекционеру, что он должен "собирать, если это необходимо". Таким образом, в мусорной среде, используяdrainпомогает системе баланс сбора метет.
Как уже отмечалось, ваш второй фрагмент кода является правильным.
Я хотел бы предложить более краткий способ использования пула авторелиза, который работает во всех средах (ref counting, GC, ARC), а также позволяет избежать путаницы слива / выпуска:
int main(void) { @autoreleasepool { NSString *string; string = [[[NSString alloc] init] autorelease]; /* use the string */ } }в приведенном выше примере обратите внимание на @autoreleasepool блок. Это задокументировано здесь.
Нет, ты ошибаешься. В документации четко указано, что в соответствии с non-GC, -drain эквивалентен-release, что означает, что NSAutoreleasePool будет не утечка.
Я нашел эту ссылку дал лучшее объяснение о том, когда и как использовать NSAutoReleasePool: AutoReleasePool
да, ваш код идеален, если бы вы использовали сбор мусора, было бы достаточно просто установить строку в ноль, когда вы закончите с ней. Сбор мусора не очень хорошо для производительности вашего приложения, поэтому я бы не рекомендовал использовать его :P
Что я читал из Apple: "В конце autorelease пул блок, объекты, которые получили сообщение autorelease в блок отправил сообщение-релиза объект получает сообщение об освобождении для каждого времени было послано сообщение autorelease внутри блока."
отправка autorelease вместо release к объекту продлевает срок службы этого объекта по крайней мере до тех пор, пока сам пул не будет осушен (это может быть дольше, если объект впоследствии сохраняется). Объект может быть помещен в один и тот же пул несколько раз, и в этом случае он получает сообщение о выпуске для каждого раза, когда он был помещен в пул.
да и нет. В конечном итоге вы освободите строковую память, но "утечка" объекта NSAutoreleasePool в память с помощью drain вместо release, если вы запустили это в среде сбора мусора (не управляемой памятью). Эта " утечка "просто делает экземпляр NSAutoreleasePool" недостижимым", как и любой другой объект без сильных указателей под GC, и объект будет очищен при следующем запуске GC, что вполне может быть непосредственно после вызова
-drain:слив
в среде сбора мусора запускает сборку мусора, если память, выделенная с момента последней сборки, превышает текущий порог; в противном случае ведет себя как выпуск. ... В среде сбора мусора этот метод в конечном итоге вызывает
objc_collect_if_needed.в противном случае, это похоже на то, как
-releaseведет себя под non-GC, да. Как утверждали другие,-releaseнет-op под GC, поэтому единственный способ сделать уверен, что бассейн работает в соответствии с ГК через-drainи-drainпод non-GC работает точно так же, как-releaseпод non-GC, и возможно связывает свою функциональность более ясно также.Я должен указать, что ваше утверждение "все, что вызывается с помощью new, alloc или init" не должно включать "init" (но должно включать "copy"), потому что "init" не выделяет память, он только устанавливает объект (конструктор моды). Если вы получили объект alloc'D и только вашу функцию вызванный init как таковой, вы не выпустили бы его:
- (void)func:(NSObject*)allocd_but_not_init { [allocd_but_not_init init]; }это не потребляет больше памяти, чем вы уже начали (предполагая, что init не создает объекты, но вы все равно не отвечаете за них).
Comments