Вопрос

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

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];
}
Это было полезно?

Решение

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

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

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

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

НСауторелизепул:дренаж против.выпускать

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

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

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

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

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

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

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

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

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

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

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

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

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

осушать

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top