NSAutoreleasePool EXC_BAD_ACCESS & Вопросы об управлении памятью в Objective-C - PullRequest
1 голос
/ 07 января 2011

Мне трудно понять, как работает NSAutoReleasePool.

1) Отслеживает ли NSAutoReleasePool каждое распределение отдельно или он зависит от переменной? Другими словами, это утечка памяти или освобождение обоих?:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
 NSArray* myObj = [NSObject alloc];  
 myObj = [NSObject alloc];  
 [pool release];

2) Почему работает следующий код:

 NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];

 NSArray* myObj = [NSObject alloc];

 for(int i = 0; i < 100; i++) {
  [myObj release];
  myObj = [NSObject alloc];
 }

 [pool1 release];

но следующее дает EXC_BAD_ACCESS в [pool1 release]:

 NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];

 NSArray* myObj = [NSObject alloc];

 NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init]; 

 for(int i = 0; i < 100; i++) {
  [myObj release];
  myObj = [NSObject alloc];
 }

 [pool2 release];
 [pool1 release];

3) Как заставить работать приведенный выше код (тот, что с 2 пулами)?

Ответы [ 3 ]

5 голосов
/ 07 января 2011

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

Поэтому ответы таковы:

  1. Утечка обоих объектов (поскольку ни один из них не освобожден и не выпущен автоматически)
  2. Это не так. Утечка последнего выделенного объекта
  3. В документации сказано, что вы можете вкладывать их . Если я предполагаю, что там, где у вас есть [NSObject alloc], вы действительно имеете в виду [[[NSObject alloc] init] autorelease], тогда ваш второй пример кода потерпит неудачу, потому что в самый первый раз, когда вы выпустите myObj, это будет для объекта, объявленного вне pool2. Это означает, что когда вы release pool1 пытаетесь освободить объект, который уже был освобожден. Способ заставить его работать - не выпускать (или автоматически освобождать) объект больше раз, чем он сохраняется или выделяется.
2 голосов
/ 07 января 2011

Несколько вещей:

: при создании объектов всегда используйте метод init. (т.е. [[NSObject alloc] init])

: объекты добавляются в AutoreleasePool после их автоматического освобождения. Объекты в этом примере просто освобождаются и поэтому не будут использовать пулы автоматического выпуска вообще. Вы можете увидеть это, удалив все пулы авто-релиза; код все еще работает нормально.

: в первом примере будет утечка памяти. Вы выделяете два объекта и никогда не отпускаете. Если бы вы выполнили их автоматическое освобождение, то, вероятно, вы бы получили то поведение, которое искали, и утечки не было бы.

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray* myObj = [[[NSObject alloc] init] autorelease];
myObj = [[[NSObject alloc] init] autorelease];
[pool release];

: Пример 2 работает, потому что вы просто размещаете, а не освобождаете объекты; ни один из которых не использует пул autorelease. Вы можете удалить код автоматического выпуска, чтобы увидеть это.

: мне не удалось воспроизвести поведение, которое вы видите в примере 3. Возможно, внутри вашего кода происходит что-то еще.

2 голосов
/ 07 января 2011

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

Когда пул автоматического выпуска освобождается, он отправляет сообщение release каждому элементу в своем списке.Если элемент был добавлен в список несколько раз, он выпускается несколько раз.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...