Для профилирования и поиска утечек памяти в root-макросах следует использовать стандартную процедуру valgrind. Чтобы сгенерировать данные для анализа выполните
Обратите внимание,что в командной строке необходимо набрать именно root.exe, а не просто root. По умолчанию, valgrind запускает модуль memcheck, однако пользователь может указать какой модуль должен выполняться с помощью опции —tool, передав в качестве аргумента имя нужного модуля, например, вот так:
В ходе своей работы, модуль memcheck определяет несколько видов ошибок работы с памятью:
- чтение или запись по неправильным адресам памяти — за границами выделенных блоков памяти и т.п;
- использование не инициализированных значений;
- ошибки освобождения памяти, например, когда блок памяти уже был освобожден в другом месте;
- использование «неправильной» функции освобождения памяти, например, использование delete для памяти, выделенной с помощью new [];
- передача некорректных параметров системным вызовам, например, указание неправильных указателей для операций чтения из буфера, указанного пользователем;
- пересечение границ блоков памяти при использовании операций копирования/перемещения данных между двумя блоками памяти.
Помимо модуля memcheck valgrind имеет следующие модули-анализаторы: cachegrind, callgrind, massif и helgrind.
Профилирование программ может осуществляться с помощью двух модулей — cachegrind и callgrind. Каждый из них собирает разную информацию. При этом нельзя полагаться на результаты работы только одного из модулей, лучше проводить поиск «узких» мест в программах на основе анализа вывода каждого из модулей.
Модуль cachegrind проводит сбор статистики по попаданию в кэш при выполнении операций чтения и записи данных и инструкций программ. Результаты собранные данным модулем по умолчанию выводятся в файл с именем cachegrind.out.<pid> (pid — идентификатор процесса).
Mодуль callgrind позволяет собрать информацию о дереве вызовов функций в программе. По умолчанию он собирает данные о количестве выполненных инструкций, зависимостях между вызывающей и вызываемой функциями и количество вызовов конкретных функций. Кроме того, можно включить эмуляцию кэшей, аналогичную cachegrind, что позволит собрать данные о доступе к памяти. Данные собранные модулем выводятся в файл callgrind.out.<pid>.
Для визуализации данных, полученных от модулей callgrind и cachegrind, существует программа — kcachegrind, которая отображает полученные данные, и позволяет выполнять навигацию по исходному коду программы. Программа позволяет отображать собранные данные различными способами — в виде таблиц, карт и графов вызова функций. Пример отображения этих данных представлен на рисунке.
Модуль massif используется для анализа выделения памяти в программах. Он собирает сведения не только о размерах блоков, выделяемых программой, но также и о том, сколько дополнительной памяти потребуется для хранения служебной информации. После завершения программы под управлением massif, valgrind выдает краткую сводку использования памяти, а подробные данные выводятся в файл massif.out.<pid>. Для анализа этих данных может использоваться программа ms_print, входящая в поставку valgrind. Эта программа может выдавать данные в виде графиков, демонстрирующих выделение памяти в программе в процессе работы.
Также valgrind содержит инструмент helgrind , позволяющий найти ошибки синхронизации в многопоточных программах. Этот модуль помогает обнаружить следующие классы ошибок:
- потенциальные блокировки (deadlocks), возникающие из-за неправильного порядка выставления блокировок;
- повреждение данных (data races) из-за неправильных, или отсутствующих блокировок на доступ к памяти;
- неправильное использование функций POSIX API. Этот класс ошибок включает в себя разные ошибки, например, рекурсивное блокирование не рекурсивного мьютекса (мьютекс — это совместно используемая переменная, которая может находиться в одном из двух состояний: заблокированном или незаблокированном) или освобождение памяти, хранящей блокировку.