Как 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];
}
572   9  

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 внутри блока."

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

отправка 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

    Ничего не найдено.