Почему автореферат особенно опасен/дорого для приложений iPhone?

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

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

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

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

Какая реальная история?

Ответ 1

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

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

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

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

(и теперь для моего комментария)

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

Ответ 2

Не стоит использовать или не использовать autorelease, потому что в некоторых случаях автореферат - это единственный способ, которым вы пройдете. Вопрос должен быть "Почему бы не использовать 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. Он не знает, что у него появился совершенно новый объект, который он должен выпустить после использования, а не какую-то ссылку на NSString, внутренне удерживаемую классом!

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

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

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

Ответ 3

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

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

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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