В CocoaTouch (iPhone OS) как найти / устранить утечки, которых не обнаружил инструмент утечки инструментов? - PullRequest
4 голосов
/ 11 ноября 2008

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

Если я смотрю на приложение в инструментах (на устройстве или в симе), оно не обнаруживает утечек. Кроме того, чистое использование памяти находится в диапазоне 600-700 Кбайт. Переход от разных представлений моего приложения увеличивает использование памяти (как и ожидалось), но когда представления и контроллеры освобождаются и освобождаются, использование памяти никогда не бывает таким низким, как было. Однако сложение обычно составляет только что-то в диапазоне 1000-2000 байт. Так что, хотя «Утечки» не показывают мне никаких утечек, я подозреваю, что где-то есть проблема. Я также посмотрел на все объекты, которые я выделяю, и все они, кажется, восстановлены, как и ожидалось. Единственные объекты, которые я вижу, которые продолжают увеличиваться, это GeneralBlock-N (где N - некоторое число)

Стоит ли обращать внимание на показатель чистого использования инструментов? Каковы будут следующие шаги в попытке диагностировать проблему?

ДОБАВЛЕНО: Я не делаю никаких вызовов для malloc () или любых библиотек CoreFoundation, которые возвращали бы буфер, за который я отвечаю. Единственные не-Obj-C звонки, которые я делаю, - это запись операторов в NSLog.

Ответы [ 5 ]

7 голосов
/ 11 ноября 2008

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

4 голосов
/ 12 ноября 2008

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

2 голосов
/ 14 ноября 2008

Вот краткое изложение того, что я узнал (благодаря отличным ответам и комментариям):

  • Распределение объектов НЕ совпадает с использованием памяти. Ответ на мой вопрос об элементе net bytes в ObjectAlloc заключается в том, что вам не следует обращать на него внимание - по крайней мере, при определении проблем с количеством используемой памяти или сбоем. Он не отражает истинное использование памяти вашего приложения.
  • Мое любопытное предположение, что ObjectAlloc показывает только память, занятую самим непосредственным объектом. Так что, если у вас есть UIImageView, для хранения различных свойств требуется всего несколько байтов, но он может указывать на изображение в памяти, занимающее кучу места. Следовательно, просмотр ObjectAlloc полезен только для того, чтобы убедиться, что вы не создаете и не храните объекты вокруг, это не даст вам представление о том, сколько памяти вы используете или сколько вы можете использовать до сбоя.
  • MemoryMonitor даст вам общее использование памяти. Вы можете ограничить просмотр только использованием вашего приложения с помощью инструмента поиска в правом нижнем углу окна инструментов.
  • ObjectAlloc и Memory Monitor (а также инструмент Leaks) являются плагинами для инструментов - на тот случай, если это не очевидно для кого-то другого. Вы можете запустить Instruments из XCode, выполнив Run -> Start with Performance Tool. Оказавшись внутри Instruments, вы можете открыть библиотеку и добавить новые плагины для мониторинга различных аспектов производительности.
2 голосов
/ 12 ноября 2008

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

То, что вы видите, это то, что вы оставили память сохраненной и на которую все еще ссылается что-то.

Особо следует обратить внимание на то, что если вы передали ссылку на класс другому как делегат, вы освобождаете его в своем методе dealloc.

Аналогичным образом, если вы подписались на какие-либо уведомления, вы должны отписаться в viewWillDisappear: (если вы используете общий метод отписки в контроллере представления, не забудьте повторно подписаться на предупреждение о предупреждении памяти.

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

По сути, следует с подозрением относиться ко всему, на что вы ссылаетесь на класс, и пытаться выяснить, как можно по возможности устранить эту ссылку (либо в dealloc, либо в viewWillDisappear: или в обоих).

0 голосов
/ 14 ноября 2008

Одна вещь, которую нужно искать, это круговые ссылки.

(я не хочу, чтобы это прозвучало покровительственно - просто хочу убедиться, что со мной все ясно :) Если объект a относится к объекту b и объекту b относится к объекту a , о «утечке», о которой сообщается, может не быть сообщения, поскольку на всю память все еще ссылаются, но это может быть осиротевший островок объектов, отделенных от вашего приложения и никогда не подлежащих восстановлению. Конечно, это может включать больше объектов ( a относится к b , b относится к c , c относится до a и т. д.).

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

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