Ubuntu System Monitor и valgrind обнаруживают утечки памяти в приложениях C ++ - PullRequest
6 голосов
/ 03 июля 2011

Я пишу приложение на C ++, которое использует некоторые внешние библиотеки с открытым исходным кодом. Я попытался взглянуть на системный монитор Ubuntu, чтобы получить информацию о том, как мой процесс использует ресурсы, и заметил, что резидентная память продолжает увеличиваться до очень больших значений (более 100 МБ). Это приложение должно работать во встроенном устройстве, поэтому я должен быть осторожен.

Я начал думать, что должны быть (некоторые) утечки памяти, поэтому я использую valgrind. К сожалению, похоже, что valgrind не сообщает о значительных утечках памяти, только некоторые незначительные проблемы в библиотеках, которые я использую, и ничего более.

Итак, я должен сделать вывод, что мой алгоритм действительно использует столько памяти? Это кажется мне очень странным ... А может, я неправильно понимаю значение столбцов системного монитора? Может ли кто-нибудь прояснить значение «Виртуальная память», «Резидентная память», «Записываемая память» и «Память» в системном мониторе применительно к профилированию программного обеспечения? Стоит ли ожидать, что эти значения сразу же представят, сколько памяти занимает мой процесс в оперативной памяти?

В прошлом я использовал инструменты, которые могли сказать мне, где я использовал память, например, Apple Profiling Tools. Есть ли что-нибудь подобное, что я могу использовать и в Linux?

Спасибо!

1 Ответ

6 голосов
/ 03 июля 2011

Еще одним инструментом, который вы можете попробовать, является библиотека /lib/libmemusage.so:

$ LD_PRELOAD=/lib/libmemusage.so vim 

Memory usage summary: heap total: 4643025, heap peak: 997580, stack peak: 26160
         total calls   total memory   failed calls
 malloc|      42346        4528378              0
realloc|         52           7988              0  (nomove:26, dec:0, free:0)
 calloc|         34         106659              0
   free|      28622        3720100
Histogram for block sizes:
    0-15          14226  33% ==================================================
   16-31           8618  20% ==============================
   32-47           1433   3% =====
   48-63           4174   9% ==============
   64-79           4736  11% ================
   80-95            313  <1% =
...

(я выхожу vim сразу после запуска.)

Возможно, гистограмма размеров блоков даст вам достаточно информации, чтобы определить, где могут происходить утечки.

valgrind очень настраивается; --leak-check=full --show-reachable=yes может быть хорошей отправной точкой, если вы еще не пробовали.


«Виртуальная память», «Резидентная память», «Записываемая память» и «Память»

Виртуальная память - это адресное пространство, которое выделено вашему приложению , выделено . Если вы запустите malloc(1024malloc(3)100);, библиотечная функция *1024* запросит 100 мегабайт хранилища у операционной системы (или обработает его из свободных списков). 100 мегабайт будут выделены с mmap(..., MAP_ANONYMOUS), , которые фактически не будут выделять память . (См. Подробности в конце страницы malloc(3).) ОС будет выделять память при первой записи каждой страницы.

Виртуальная память учитывает все библиотеки и исполняемые объекты, которые отображаются в вашем процессе, а также пространство стека.

Резидентная память - это объем памяти, фактически равный в ОЗУ . Вы можете ссылаться на всю 1,5-мегабайтную библиотеку C, но использовать только 100 Кбайт (дикое предположение) библиотеки, необходимой для поддержки стандартного интерфейса ввода-вывода. Остальная часть библиотеки будет по требованию выгружаться с диска, когда это необходимо. Или, если ваша система испытывает недостаток памяти и некоторые неиспользуемые в последнее время данные выгружаются для подкачки, она больше не будет учитываться в резидентной памяти .

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

Поскольку в вашей системе одновременно может быть от 50 до 100 процессов, и почти все они связаны со стандартной библиотекой C, все процессы получают share отображений памяти только для чтения для библиотеки. (Они также могут совместно использовать все сопоставления при записи private writeable для любых файлов, открытых с mmap(..., MAP_PRIVATE|PROT_WRITE), до тех пор, пока процесс не выполнит запись в память.) Инструмент top(1) сообщит количество память, которую можно разделить между процессами в столбце SHR. (Обратите внимание, что память может не совместно использоваться, но часть ее (libc) определенно является общей.)

Память очень расплывчата. Я не знаю, что это значит.

...