Правильный подход для проверки выделения памяти в Objective C - PullRequest
6 голосов
/ 02 января 2011

Мне интересно, какой будет правильный подход после выполнения команды, которая выделяет память в Objective C (я в основном имею в виду приложения для iOS). Моя дилемма связана с тем фактом, что проверка на успешность сбоя операции выделения памяти добавляет много строк кода, хотя интересно, будет ли это вообще полезно. Кроме того, иногда выделение памяти очевидно, например, использование «alloc», но иногда они происходят за кулисами. И даже если мы проверим каждое распределение - когда мы обнаружим, что оно провалилось - мы мало что можем сделать. Так что, возможно, правильный подход - просто дать ему сбоить и вызвать сбой приложения? Посмотрите на этот код:

// Explicit memory allocation
NSArray a1 = [[NSArray alloc] initWithObjects:someObj, nil];
if (!a1) {
  // Should we make this check at all? Is there really what to do?
}

// Implicit memory allocation
NSArray a2 = [NSArray arrayWithObjects:someObj, nil];
if (!a2) {
  // should we make this check at all? Is there really what to do?
}

Какой, по вашему мнению, будет правильный подход? Проверять или нет проверять наличие ошибок выделения? Разработчики iOS - как вы справились с этим в своих приложениях?

Ответы [ 4 ]

11 голосов
/ 02 января 2011

Fantasy: Каждое выделение памяти будет проверено, и любой сбой будет сообщен пользователю дружественным образом, приложение будет корректно закрыто, будет отправлен отчет об ошибке, вы можете исправить это и следующая версия была бы идеальной [в этом случае].

Реальность: К тому времени, когда что-то столь же тривиальное, как arrayWithObjects:, выходит из строя, ваше приложение уже давно, очень давно умерло. Там нет восстановления в этом случае. Вполне вероятно, что фреймворки уже потерпели неудачу при выделении и уже повредили состояние вашего приложения.

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

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

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

Ваше первое нападение на сокращение памяти происходит в процессе проектирования и разработки. Вы должны рассмотреть использование памяти с самого начала процесса разработки приложения, и вы должны оптимизировать использование памяти, так как вы полируете свое приложение для публикации. Воспользуйтесь инструментом Allocations (см. Эту статью для анализа Heapshot , которую я сделал несколько лет назад - она ​​очень применима) и оправдывайте существование каждого крупного потребителя памяти.

2 голосов
/ 09 марта 2012

Приложения iPhone должны регистрироваться для уведомлений UIApplicationDidReceiveMemoryWarningNotification. iOS отправит их, когда доступной памяти станет мало. Google iphoneappprogrammingguide.pdf (от 12.10.2011) для получения дополнительной информации.

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

Это действительно сложная проблема, потому что это случается очень редко (для хорошо разработанных программ). В мире ПК / мини / мэйнфреймов виртуальная память практически устраняет проблему, но в большинстве патологических программ. В системах с ограниченной памятью (таких как смартфоны) стресс-тестирование вашего приложения с помощью инструмента мониторинга кучи должно дать вам хорошее представление о его максимальном использовании памяти. Вы можете написать код программы-обертки для верхней отметки для alloc, который делает то же самое.

0 голосов
/ 02 января 2011

С мощью, которую вы имеете в Iphone / смартфоне, время, необходимое для вычисления нескольких тестов, смешно думать «действительно ли стоит проверить», это всегда хороший тест и выявлять любые сбои в вашем коде / распределениях,(если вы этого не сделаете, это будет больше похоже на ваш ленивый добавить несколько дополнительных строк в ваш код.

Кроме того, "позволить сбой приложения" дает действительно плохое впечатление о вашем приложении, пользователь видит приложение закрытьбез причины и считает его программным обеспечением низкого качества. Вы должны всегда добавлять свои тесты, и если вы ничего не можете сделать с ошибкой, то, по крайней мере, вы должны отобразить сообщение до закрытия приложения (делает пользователя менее расстроенным).

есть несколько опций для отслеживания выделения памяти, например, перехват исключений. Проверка, равен ли возвращаемый указатель ноль, проверка размера списка и т. Д.

вам следует подумать о способах запуска приложенияв случае неудачного выделения:

  • если это просто представление вашего интерфейса, выведите сообщение о том, что не удалось загрузить конкретное представление ...

  • если это основной и единственный вид, изящно закройте приложение сообщением

...

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

0 голосов
/ 02 января 2011

Проверьте их, подтвердите в отладке (чтобы вы знали, где / почему существуют сбои) и передайте ошибку клиенту (в большинстве случаев). У клиента, как правило, больше контекста - повторяются ли они с меньшим запросом? потерпеть неудачу как-нибудь? отключить функцию? Отображение оповещения для пользователя и т. Д. И т. Д. Приведенные вами примеры не являются концом света, и вы можете изящно оправиться от многих - кроме того, вам необходимо (или должно знать), когда и где ваши программы терпят неудачу.

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