Как найти утечку памяти, которая не является утечкой памяти?

#c #debugging #memory #memory-leaks

Вопрос:

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

Обычно это была бы утечка памяти, однако я использовал libasan и valgrind, и ни один из них не может найти утечку.

Я подозреваю, что происходит то, что где-то внутри кода динамическая структура растет бесконтрольно из-за логической ошибки. Например, вектор, который снова и снова резервируется со все большими значениями. Что касается asan, это не memleak, так как он очищается после завершения программы, но будет иметь точно такие же последствия.

Какие инструменты можно использовать, чтобы попытаться определить, какие объекты в памяти являются самыми большими? т. е. попытаться обнаружить «утечку памяти», которая на самом деле не является утечкой.

Комментарии:

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

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

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

4. Затем вам нужно добавить ведение журнала. Регистрируйте каждый раз, когда создается новый объект (включая добавление в контейнер) и когда объекты уничтожаются. Убедитесь, что все творения соответствуют разрушению.

5. Профилировщик памяти (например, инструмент массива valgrind или инструмент «Распределения», который является частью пакета инструментов macOS/X’/X-Code) может быть здесь очень полезен; когда ваша программа находится в состоянии раздутости/сбоя, она может сообщить вам, какие распределения составляют основную часть использования оперативной памяти процесса. Это, в свою очередь, даст вам подсказку о том, откуда исходит ваша не-утечка-утечка.

Ответ №1:

Попробуй https://github.com/vmware/chap

Это поможет вам, потому что он вычисляет график ссылок между распределениями, а также распознает многие из различных видов распределений, используемых контейнерами std.

Запустите свой процесс без документов, пока он не станет значительно больше, чем вы ожидаете, затем используйте gcore для сбора живого ядра, откройте ядро в главе и начните с предложений в https://github.com/vmware/chap/blob/master/USERGUIDE.md#analyzing-memory-growth

Ответ №2:

Мне рекомендовали heaptrack и heaptrack_gui для решения этой проблемы в Linux, и он делает именно то, что мне нужно для решения этой проблемы. Он показывает вам график распределения памяти на основе иерархии вызовов, чтобы вы могли сузить, звонок за звонком, где вы, скорее всего, перерасходуете.

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