Я использую valgrind (v3.10.0) для поиска утечки памяти в сложном приложении (сильно модифицированная сборка net-snmp), которая строится как часть более крупного программного пакета. Я уверен, что есть утечка (объем памяти приложения растет линейно без ограничений), но valgrind всегда сообщает о завершении после следующего.
==1139== HEAP SUMMARY:
==1139== in use at exit: 0 bytes in 0 blocks
==1139== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==1139==
==1139== All heap blocks were freed -- no leaks are possible
Общее использование кучи не может быть нулевым - в приложении malloc
и free
есть много, много вызовов. Valgrind все еще способен обнаруживать ошибки "Invalid Write".
Скомпилированное приложение вместе с другими пакетами программного обеспечения компилируется с помощью инструментальной цепочки uclibc-gcc для процессора MIPS (uclibc v0.9.29), который должен быть свернут на встроенное устройство, работающее с linux-оболочкой busybox (v1.17.2), Я запускаю valgrind прямо на устройстве. При запуске Valgrind я использую следующие параметры:
--tool=memcheck --leak-check=full --undef-value-errors=no --trace-children=yes
В принципе, Valgrind не обнаруживает никакого использования кучи, хотя я использовал кучу. Почему это может быть? Являются ли какие-либо из моих предположений (ниже) неправильными?
Что я пробовал
Простая тестовая программа
Я скомпилировал простую тестовую программу (используя ту же цель и инструментальную цепочку, что и приложение выше) из учебника быстрого обучения Valgaind , чтобы узнать, обнаружит ли Valgrind протечь. Конечный результат был таким же, как и выше: без использования кучи.
Связанные проблемы?
Документация Valgrind имеет следующие ответы на их часто задаваемые вопросы:
Если ваша программа статически связана, большинство инструментов Valgrind будут работать только хорошо, если они смогут заменить некоторые функции, такие как malloc, своими версиями. По умолчанию статически связанные функции malloc не заменяются. Ключевым показателем этого является то, что Memcheck говорит: "Все блоки кучи были освобождены - утечки не возможны".
Вышеупомянутое звучит точно так же, как и моя проблема, поэтому я проверил, что он динамически связан с библиотеками C, содержащими malloc
и free
. Я использовал исполняемый файл uclibc toolchain ldd
executable (я не могу использовать родной linux ldd
), а вывод включал следующие строки:
libc.so.0 => not found (0x00000000)
/lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)
(Причина, по которой они не найдены, заключается в том, что я запускаю это на хост-устройстве x86, целевое устройство mips не имеет исполняемого файла ldd.) Исходя из моего понимания, malloc
и free
быть в одной из этих библиотек, и они, похоже, динамически связаны. Я также выполнил readelf
и nm
в исполняемом файле, чтобы подтвердить, что ссылки на malloc
и free
равны undefined (что характерно для динамически связанного исполняемого файла).
Кроме того, я попробовал запустить Valgrind с опцией --soname-synonyms=somalloc=NONE
, как это было предложено в FAQ.
Поддержка LD_PRELOAD?
Как отмечают комментаторы и ответчики, Valgrind зависит от использования LD_PRELOAD. Было высказано предположение, что моя инструментальная цепочка не поддерживает эту функцию. Чтобы подтвердить, что это так, я последовал за этим примером, чтобы создать простую тестовую библиотеку и загрузить ее (я заменил rand()
на функцию, которая возвращает 42). Тест работал, поэтому кажется, что моя цель поддерживает LD_PRELOAD просто отлично.
Данные эльфа
Я также включу некоторую информацию из команды readelf
, которая может быть полезна. Вместо гигантского дампа я урезал все, чтобы включить только то, что может быть релевантным.
Dynamic section
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libnetsnmpagent.so.30]
0x00000001 (NEEDED) Shared library: [libnetsnmpmibs.so.30]
0x00000001 (NEEDED) Shared library: [libnetsnmp.so.30]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so.0]
0x0000000f (RPATH) Library rpath: [//lib]
Symbol table '.dynsym'
Num: Value Size Type Bind Vis Ndx Name
27: 00404a40 0 FUNC GLOBAL DEFAULT UND free
97: 00404690 0 FUNC GLOBAL DEFAULT UND malloc