Почему iOS закрывает мое приложение, даже когда я освобождаю много памяти в ответ на предупреждения памяти? - PullRequest
8 голосов
/ 14 декабря 2011

Я не могу понять, почему iOS закрывает мое приложение (iPad, iOS 4) из-за использования памяти, даже после того, как я освобождаю тонну памяти в ответ на предупреждения о нехватке памяти. Например, вот типичный сценарий завершения, в котором я часто регистрирую использование памяти - посмотрите на использование «приложения», первое значение КБ в каждой строке:

...
2011-12-14 13:25:42.343 Oyster[211:707] Memory usage (KB): app 268256, delta 6472, used 366800/373940
2011-12-14 13:25:43.292 Oyster[211:707] Memory usage (KB): app 273900, delta 5644, used 372444/381024
2011-12-14 13:25:44.159 Oyster[211:707] Memory usage (KB): app 282920, delta 9020, used 381464/389116
2011-12-14 13:25:45.184 Oyster[211:707] Memory usage (KB): app 272140, delta -10780, used 370684/379432
2011-12-14 13:25:46.109 Oyster[211:707] Memory usage (KB): app 260412, delta -11728, used 358956/365900
2011-12-14 13:25:48.443 Oyster[211:707] Received memory warning. Level=2
2011-12-14 13:25:48.454 Oyster[211:707] Memory usage (KB): app 9172, delta -251240, used 107716/112548
(gdb)

Вы можете видеть увеличение использования памяти приложением, пока оно не получит предупреждение памяти. Тогда я правильно отвечаю на предупреждение о памяти и освобождаю кучу (250 МБ!) Памяти. В этот момент мое приложение закрывается, и iOS переходит на домашний экран iPad.

Журналы «Использование памяти» здесь отображаются с моей logMemoryUsage () функцией , которая основана на коде из этого ответа .

Для записи я использую SDWebImage для кэширования UIImages в памяти, но, как показано, он обрабатывает предупреждения памяти, опустошая свой кэш (довольно большой на данный момент). Я понимаю, что могу настроить кеширование SDWebImage, чтобы не заполнять всю доступную память, и просто ждать предупреждений о памяти, но напрашивается следующий вопрос ...

Почему iOS завершает работу моего приложения, хотя я отвечаю на предупреждения памяти, счастливо освобождая тонну памяти?

Ответы [ 5 ]

11 голосов
/ 16 декабря 2011

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

  1. Предупреждения в памяти не являются «плохими» по своей природе, и вы не можете их избежать. Они являются обычной частью жизненного цикла iOS, и вы должны обрабатывать их правильно, выпуская все несущественные данные во всех ваших объектах, чтобы гарантировать, что ваше приложение ведет себя ответственно. Даже если ваше приложение занимает небольшую площадь, вы все равно можете получить в памяти предупреждение о других состояниях на рассматриваемом устройстве (например, других используемых приложениях и т. Д.). Я имею в виду уведомление об исполнении UIApplicationDidReceiveMemoryWarningNotification здесь. Сообщения отладчика (например, «Предупреждение о получении памяти. Уровень = 2») относятся к вашему приложению, хотя они не обязательно связаны с получением уведомления во время выполнения.

  2. Я не знаю много о SDWebCache. Я бы посмотрел на реализацию и убедился, что она эффективно высвобождает память. Например, использование @autoreleasepool в соответствующих местах поможет более эффективно высвобождать объекты в цикле выполнения.

  3. Вы должны стремиться к тому, чтобы объем памяти вашего приложения был как можно более ограниченным. нормально использовать кэш в памяти для данных изображения, но я бы ограничил его размер. Если размер вашего приложения превышает 250 МБ, я не удивлюсь, что его работа прекращается, даже если вы обрабатываете предупреждения памяти. Скорее всего, уже слишком поздно.

  4. У вас могут быть другие проблемы, вызывающие / способствующие прекращению. Как уже отмечалось в комментариях, вам нужно больше отладки в инструментах для поиска утечек, плохого доступа и т. Д. Публикация здесь журнала сбоев была бы полезна.

1 голос
/ 23 декабря 2011

При работе с большими изображениями (4 МБ на изображение) вы можете столкнуться с риском нехватки памяти без предупреждения о недостаточном объеме памяти.

Лучше всего предотвратить слишком интенсивное использование памяти. Скорость загрузки изображений такова, что кэширование хорошо, но не обязательно. Гораздо лучше уменьшить потребление, освободив память, как только вы ее больше не используете.

Удачи и дайте нам знать, если найдете что-то, что стоит поделиться.

1 голос
/ 23 декабря 2011

Предупреждение памяти уровня 2: Срочно .Ваше приложение, вероятно, получает одно или несколько предупреждений уровня 1 до получения предупреждения уровня 2, и вы должны действовать в этот момент.

По моему опыту, когда ваше приложение получает предупреждение уровня 2, почти всегда слишком поздно, иего все равно убьют.

1 голос
/ 22 декабря 2011

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

У меня была такая же проблема в моем приложении.Я пытался прокомментировать код трансформации.Проблема была решена.Вы также можете попробовать.

1 голос
/ 15 декабря 2011

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

  • Неизвестные циклические ссылки не позволяют памяти работатьосвобожден, как вы ожидаете.Используйте инструменты, чтобы искать их.Недавно я зафиксировал случай, в котором я случайно использовал себя в блоке, вызывая сохранение.Мы заметили это, когда появилось предупреждение о памяти, и мы не смогли полностью восстановиться из предупреждения, выпустив этот ресурс.
  • Очистка ресурсов - или автоматическое освобождение ресурсов - выпустила что-то, что по-прежнему необходимо.У вас может быть ноль, если вы этого не ожидаете, или вы можете оперировать зомби.Проверьте вашу задержку и очистку, особенно nilling делегатов.Включите зомби и точку останова исключения.

Обычно лучшим решением является предотвращение появления предупреждения памяти в первую очередь.

...