iOS - решение @autoreleasepool для сбоя или обходного пути?

Так что приложение зависало без отслеживания стека или каких-либо исключений, и я мог повторять этот сбой каждый раз. Моей первой мыслью было, что это должен быть двойной релиз, после 10-минутного запуска зомби я не смог заставить приложение рухнуть ни разу.

Посмотрев на Распределения, я заметил огромный скачок в размерах выделенных объектов при вызове метода. Таким образом, я получил @autoreleasePool внутри цикла for. этот пул автоматического выпуска исправил ошибку; но как я могу подтвердить, что это действительно было нехватка памяти? (didRecieveMemoryWarning не вызывался ни в какое время до сбоя)

Почему autoreleasePool решает проблему?

Почему не вызывается ReecieveMemoryWarning? Это потому, что приложению не хватает памяти, прежде чем мы доберемся до конца текущего цикла выполнения?

- (void)doSomething
{

   for (Item *item in self.items)
   {
      @autoreleasepool
      {
         // A bunch of initializations here that take a lot of memory
      }
   }

}

3 ответа

Решение

Используйте инструменты для отслеживания распределения и определения, растет ли оно без пула авто-релиза.

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

Авто-выпуск устраняет проблему, скорее всего, потому, что во время инициализации создается масса автоматически выпущенных объектов. Бассейн не будет осушен, пока не завершится цикл.

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

Это работает в том же потоке UIApplicationMain? Распределяет ли область видимости множество объектов с помощью alloc/init? ARC включен?

Пул @autorelease - это часть кучи, отвечающая за объекты, выделенные без явного вызова init, например, /[NSString stringWithFormat: "% @", format]/ или возвращенная с автоматическим выпуском, например /[[[NSObject alloc] init] autorelease]/,

Проблема, должно быть, исчезла, потому что каждый раз, когда вы достигаете конца цикла, он выполняет [утечку пула], освобождая любые статически размещенные объекты в этой области. Я бы посоветовал вам создать еще один поток для выполнения этого распределения и приостановить основной поток между ними (может быть, с помощью UIAlertView?). Когда вы создаете autoreleasepool внутри другого autoreleasepool, второй может застрять в первом, который будет выпущен только в конце приложения. Надеюсь, поможет.

Другие вопросы по тегам