Как отлаживать утечки памяти, когда инструмент Leaks не показывает их?

У меня есть приложение iOS, написанное в Swift, которое пропускает память - в определенной ситуации некоторые объекты должны быть выпущены, но это не так. Я узнал об этой проблеме, просто добавив deinit отладочные сообщения следующим образом:

deinit {
    println("DEINIT: KeysProvider released")
}

Итак, сообщение deinit должно присутствовать в консоли после таких событий, которые должны вызывать публикацию объекта. Однако для некоторых объектов, которые должны быть выпущены, сообщение отсутствует. Тем не менее, у Leaks Developer Tool нет утечек. Как решить такую ​​ситуацию?

Ответ 1

В Xcode 8 вы можете нажать на кнопку "График отладочной памяти", debugmemorygraphbutton на панели инструментов отладки (показанной внизу экрана):

debug memory graph

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

Обратите внимание, что на правой панели я вижу дерево вызовов. Я получил это, включив опцию ведения журнала "malloc stack" в настройках схемы:

malloc stack

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

code

Вышеупомянутый метод диагностики памяти (и больше) продемонстрирован в последней части WWDC 2016 Visual Debugging with Xcode.


Традиционная техника инструментов (особенно полезная при использовании более старых версий Xcode) описана ниже, в моем первоначальном ответе.


Я бы предложил использовать инструмент "Распределение" инструментов с функцией "Record Reference Counts":

record reference counts

Затем вы можете запустить приложение в разделе "Инструменты", а затем выполнить поиск своего класса, который, как вы знаете, протекает, и развернуть его, нажав на стрелку:

enter image description here

Затем вы можете углубиться в детали и посмотреть трассировку стека, используя панель "Расширенные детали" справа:

extended details

На этой панели "Расширенные сведения" сосредоточьтесь на коде черного цвета, а не на системных вызовах серого цвета. В любом случае, на панели "Расширенные сведения" вы можете перейти к исходному коду прямо в Инструменты ::

your code

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

Ответ 2

Используйте инструменты для проверки утечек и потери памяти из-за сохраненной, но не просочившейся памяти. Последняя - неиспользуемая память, на которую все еще указывают. Используйте Mark Generation (Heapshot) в инструменте Allocations на инструментах.

Для того, чтобы использовать Heapshot для поиска памяти, см. блог bbum

В основном метод состоит в том, чтобы запускать инструменты, выделять инструмент, делать снимок, запускать итерацию вашего кода и повторять еще один кучей, повторяя 3 или 4 раза. Это будет указывать на память, которая выделяется и не выдается во время итераций.

Чтобы выяснить, какие результаты раскрываются, чтобы увидеть отдельные распределения.

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

Запуск в инструментах, в поле "Абонирование" задано значение "Запись отсчетов" (для Xcode 5 и ниже вы должны остановить запись, чтобы установить параметр). Причина, по которой приложение запускается, останавливает запись, разворачивается, и вы сможете увидеть, где все сохраняется, выпуски и автореализаторы.