![]() Логотип Valgrind | |
Оригинальный автор(ы) | Джулиан Сьюард , Николас Нетеркот [1] |
---|---|
Разработчик(и) | Команда разработчиков Valgrind [2] |
Первоначальный выпуск | 27 июля 2002 г. [3] |
Стабильный релиз | 3.23.0 (26 апреля 2024 г [±] [4] ( 2024-04-26 ) | )
Репозиторий |
|
Написано в | С |
Операционная система | Linux FreeBSD Solaris Android [5] |
Тип | Профилировщик , отладчик памяти |
Лицензия | Стандартная общественная лицензия GNU |
Веб-сайт | www.valgrind.org |
Valgrind ( / ˈ v æ l ɡ r ɪ n d / ) [6] — это программный инструмент для отладки памяти , обнаружения утечек памяти и профилирования .
Valgrind изначально разрабатывался как свободно лицензируемый инструмент отладки памяти для Linux на платформе x86 , но с тех пор превратился в универсальную платформу для создания инструментов динамического анализа, таких как средства проверки и профилирования.
Valgrind по сути является виртуальной машиной , использующей методы компиляции just-in-time , включая динамическую перекомпиляцию . Ничто из исходной программы никогда не запускается напрямую на хост -процессоре . Вместо этого Valgrind сначала транслирует программу во временную, более простую форму, называемую промежуточным представлением (IR), которая является нейтральной к процессору статической формой с одним присваиванием . После преобразования инструмент (см. ниже) может свободно выполнять любые преобразования в IR, прежде чем Valgrind транслирует IR обратно в машинный код и позволяет хост-процессору запустить его. Valgrind перекомпилирует двоичный код для запуска на хост- и целевом (или имитируемом) процессорах той же архитектуры. Он также включает заглушку GDB , позволяющую отлаживать целевую программу во время ее работы в Valgrind, с «командами монитора», которые позволяют запрашивать у инструмента Valgrind различную информацию.
При этих преобразованиях теряется значительная часть производительности (и, как правило, код, вставляемый инструментом); обычно код, запущенный с помощью Valgrind и инструмента «none» (который ничего не делает с IR), работает со скоростью от 20% до 25% от скорости обычной программы. [7] [8]
В Valgrind включено несколько инструментов (и несколько внешних). Инструмент по умолчанию (и наиболее используемый) — Memcheck . Memcheck вставляет дополнительный код инструментирования вокруг почти всех инструкций, который отслеживает действительность ( вся нераспределенная память начинается как недействительная или «неопределенная», пока она не будет инициализирована в детерминированное состояние, возможно, из другой памяти) и адресуемость (указывает ли рассматриваемый адрес памяти на выделенный, не освобожденный блок памяти), хранящуюся в так называемых битах V и битах A соответственно. По мере перемещения или манипулирования данными код инструментирования отслеживает биты A и V, поэтому они всегда верны на однобитовом уровне.
Кроме того, Memcheck заменяет стандартные распределители C++ и распределитель памяти C собственной реализацией, которая также включает защиту памяти вокруг всех выделенных блоков (с битами A, установленными на «недопустимое»). Эта функция позволяет Memcheck обнаруживать ошибки с превышением на единицу , когда программа считывает или записывает за пределами выделенного блока на небольшую величину. Проблемы, которые Memcheck может обнаружить и о которых предупредить, включают следующее:
free
'dmalloc
'd блоковmem*
иstr*
malloc
иdelete
new
иdelete[]
realloc
с размером нольЦена этого — потеря производительности. Программы, работающие под Memcheck, обычно работают в 20–30 раз медленнее [9] , чем работающие вне Valgrind, и используют больше памяти (есть штраф памяти за выделение). Таким образом, немногие разработчики запускают свой код под Memcheck (или любым другим инструментом Valgrind) все время. Чаще всего они используют такие инструменты либо для отслеживания какой-то конкретной ошибки, либо для проверки отсутствия скрытых ошибок (таких, которые может обнаружить Memcheck) в коде.
Помимо Memcheck, Valgrind имеет несколько других инструментов: [10]
exp-sgcheck (называвшийся exp-ptrcheck до версии 3.7) был удален в версии 3.16.0. Это был экспериментальный инструмент для поиска ошибок переполнения стека и глобального массива, которые Memcheck не может найти.
Также доступно несколько инструментов, разработанных внешними разработчиками. Одним из таких инструментов является ThreadSanitizer, еще один детектор состояний гонки . [12] [13]
Начиная с версии 3.4.0, Valgrind поддерживает Linux на x86 , x86-64 и PowerPC . Поддержка Linux на ARMv7 (используется, например, в некоторых смартфонах ) была добавлена в версии 3.6.0. [14] Поддержка Solaris была добавлена в версии 3.11.0. [5] Поддержка OS X была добавлена в версии 3.5.0. [15] Поддержка FreeBSD x86 и amd64 была добавлена в версии 3.18.0. Поддержка FreeBSD aarch64 была добавлена в версии 3.23.0. Существуют неофициальные порты на другие Unix-подобные платформы (например, OpenBSD , [16] NetBSD [17] и QNX [18] ). С версии 3.7.0 была добавлена поддержка платформы ARM/ Android . [5]
Начиная с версии 3.9.0, есть поддержка Linux на MIPS64 little and big endian, MIPS DSP ASE на MIPS32 , инструкций s390x Decimal Floating Point, инструкций POWER8 ( Power ISA 2.07 ), инструкций Intel AVX2 , Intel Transactional Synchronization Extensions, как RTM, так и HLE, а также начальная поддержка аппаратной транзакционной памяти на POWER. [4]
Название Valgrind является отсылкой к главному входу в Вальхаллу из скандинавской мифологии . [19] [20] Во время разработки (до выпуска) проект назывался Heimdall ; однако это название противоречило бы пакету безопасности.
Первоначальным автором Valgrind является Джулиан Сьюард , который в 2006 году получил премию Google-O'Reilly Open Source Award за свою работу над Valgrind. [21] [22]
Несколько других также внесли значительный вклад, включая Николаса Нетеркота, Барта Ван Аша, Флориана Крома, Тома Хьюза, Филиппа Варокьера, Марка Вилаарда, Пола Флойда, Петара Йовановича, Карла Лава, Сериона Армор-Брауна и Иво Райсра. [23]
Он используется рядом проектов на базе Linux. [24]
Помимо снижения производительности, важным ограничением Memcheck является его неспособность обнаружить все случаи ошибок границ при использовании статических или выделенных в стеке данных. [25] Следующий код пройдет проверку Memcheck в Valgrind без происшествий, несмотря на то, что содержит ошибки, описанные в комментариях:
int Static [ 5 ]; int func ( void ) { int Stack [ 5 ]; Static [ 5 ] = 0 ; /* Ошибка - Static[0] to Static[4] существуют, Static[5] выходит за пределы */ Stack [ 5 ] = 0 ; /* Ошибка - Stack[0] to Stack[4] существуют, Stack[5] выходит за пределы */ return 0 ; }
Неспособность обнаружить все ошибки, связанные с доступом к данным, размещенным в стеке, заслуживает особого внимания, поскольку определенные типы ошибок стека делают программное обеспечение уязвимым для классического эксплойта с разрушением стека .