Почему авто-релиз особенно опасен / дорог для приложений iPhone? - PullRequest
14 голосов
/ 05 марта 2009

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

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

SO ссылки:
autorelease-iphone
Почему это приводит к утечке памяти (iPhone)?

Примечание: с концептуальной точки зрения я вижу, что autorelease немного дороже, чем простой вызов release, но я не думаю, что небольшого штрафа достаточно, чтобы Apple рекомендовала против него .

Какая настоящая история?

Ответы [ 5 ]

11 голосов
/ 05 марта 2009

(не можете принять свой ответ?)

Что ж, после всего этого мне удалось найти ссылку от Apple Developer, добавленную в качестве примечания в нижней части страницы:

Примечание для iPhone OS: потому что на iPhone OS приложение выполняется в более ограниченная памятью среда, использование авто-релизных пулов не рекомендуется в методах или блоках код (например, циклы), где Приложение создает много объектов. Вместо этого вы должны явно выпустить объекты, когда это возможно.

Тем не менее, это предполагает осторожное использование авто-релиза, а не его полное избегание.

(а теперь и мой комментарий)

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

9 голосов
/ 06 января 2011

Вопрос не в том, использовать или не использовать авто-релиз, потому что в некоторых случаях авто-релиз - единственный путь, через который вы можете пройти. Вопрос должен звучать так: « Почему бы не использовать autorelease для всех объектов вместо использования retain и release? ».

Чтобы ответить на этот вопрос, вы должны сначала узнать, как правильно использовать autorelease. Допустим, у вас есть класс с двумя свойствами: firstName и lastName. Для каждого есть геттер и сеттер. Но вам также нужен метод, который бы возвращал fullName путем объединения этих двух строк в совершенно новую строку:

- (NSString *) fullName {
   NSString str = [[NSString alloc]initWithFormat:@"%@ %@", firstName, lastName];
   // this is not good until we put [str autorelease];
   return str;
}

Что не так с этой картинкой? Счетчик ссылок в возвращаемой строке равен 1, поэтому, если вы не хотите, чтобы утечка произошла, вызывающий должен освободить ее, когда он закончил. С точки зрения вызывающего, он просто запросил значение свойства fullName. Он не знает о том факте, что он получил совершенно новый объект, который он должен выпустить после использования, а не какую-то ссылку на строку NSSt, внутренне принадлежащую классу!

Если мы поместим [str release] перед возвратом, строка будет уничтожена, а метод вернет мусор! Здесь мы используем [str autorelease], чтобы пометить объект для освобождения в более позднее время (как правило, когда обработка события завершена). Таким образом, вызывающий объект получает свой объект, и ему не нужно беспокоиться о том, должен он его отпустить или нет.

Соглашение состоит в том, чтобы вызывать autorelease для нового объекта, прежде чем метод вернет его вызывающей стороне. Исключением являются методы с именами, которые начинаются с alloc, new или copy. В таких случаях вызывающие абоненты знают, что для них создан совершенно новый объект, и они обязаны вызывать функцию освобождения для этого объекта.

Замена релиза с помощью автоматического выпуска - плохая идея, так как объекты очень быстро накапливаются и забивают память, особенно в циклах. Ресурсы на iPhone ограничены, поэтому для минимизации перегрузки памяти вы обязаны освободить объект, как только закончите с ним.

5 голосов
/ 05 марта 2009

Я не согласен с тем, что избегать авто-релиза в целом разумно.

Cocoa Touch использует его довольно часто внутри страны, и во многих ситуациях это единственный способ правильно распределить память (хороший пример - многократно используемые ячейки табличного представления). Если вы понимаете, что происходит, пул автозапуска - отличный инструмент в вашем распоряжении. Главное, что нужно помнить, это то, что блоки не освобождаются до некоторого момента в цикле выполнения. Если вы выполняете замкнутый цикл без взаимодействия с пользователем и накапливаете блоки автоматического выпуска, в конечном итоге вам не хватит памяти.

Авто-выпуск не заменяет сборку мусора (недоступно в iPhone SDK) и может привести к неприятным ошибкам в виде повисшего указателя (указатель все еще кажется хорошим, но в некоторой непредсказуемой точке становится недействительным), но также очень полезно при написании понятного и простого в обслуживании кода. Рассмотрим следующий случай:

[aDictionary writeToFile:
     [documentsDirectory stringByAppendingPathComponent:@"settings.plist"]
              atomically:YES];

Строка пути генерируется как объект автоматического выпуска. Мы не обязаны создавать временный объект, поэтому мы избегаем этих накладных расходов (и возможности, которые мы могли бы забыть выпустить). Память будет полностью освобождена (без утечек), просто это произойдет позже в цикле выполнения. Спросите себя: собираюсь ли я выделить сотни из них, прежде чем вернуться к пользовательскому вводу? Если нет (как было бы здесь), autorelease - отличное решение, и этот метод NSString для работы с путями доступен только с использованием автоматически освобожденной памяти.

Я согласен с вышеприведенным постером, что следовать соглашению и быть последовательным - очень хорошая идея.

4 голосов
/ 06 марта 2009

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

Как подчеркивает Apple, особая проблема возникает, когда вы используете автоматически выпущенные объекты в любом виде цикла, потому что они накапливаются в пуле автоматического выпуска. Затем вам нужно решить, когда нужно слить пул или создать / освободить его. Выполнение этого при каждом прохождении цикла может снизить производительность, но слишком большое количество проходов может привести к опасному использованию памяти. Я все еще настраиваю это в Molecules, потому что возникают проблемы с памятью при импорте больших (> 2 МБ) текстовых файлов из банка протеиновых данных. Мне удалось улучшить производительность за счет минимизации автоматически выпущенных объектов, но я не смог их полностью устранить.

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

0 голосов
/ 05 марта 2009

Я бы настоятельно рекомендовал избегать автоматического выпуска, как чума. Ошибки в управлении памятью - отличный способ тратить огромное количество времени и денег, я имел сомнительную честь много раз проходить этот процесс на старых приложениях Mac, и тот факт, что iPhone имеет жесткие ограничения памяти, означает, что у вас будьте предельно осторожны, иначе приложение просто будет нестабильным и часто зависает ... как многие из первых приложений, выпущенных прошлым летом.

Единственный надежный способ написать стабильные приложения для iPhone - это самостоятельно управлять всей своей памятью и делать это последовательно. Даже если вы являетесь единственным программистом в своем проекте, вы поблагодарите себя позже. Это может быть сложно, если вы научились программировать на языках, которые «обо всем позаботятся за вас», но действительно стоит научиться хорошо, если вы серьезно относитесь к созданию качественных приложений для iPhone.

...