Валгринд - Valgrind

Валгринд
Valgrind logo.png
Оригинальный автор (ы) Джулиан Сьюард
Разработчики) Команда разработчиков Valgrind
Стабильный выпуск 3.16.1 (22 июня 2020 г . ; 6 месяцев назад ) [±]  ( 2020-06-22 )
Репозиторий Отредактируйте это в Викиданных
Операционная система Linux
macOS
Solaris
Android
Тип Профайлер , отладчик памяти
Лицензия Стандартная общественная лицензия GNU
Веб-сайт www .valgrind .org

Valgrind ( / v æ л ɡ г ɪ п д / ) представляет собой программный инструмент для отладки памяти , утечка памяти обнаружения и профилирования .

Valgrind изначально разрабатывался как инструмент для отладки свободной памяти для Linux на платформе x86 , но с тех пор превратился в общую платформу для создания инструментов динамического анализа, таких как средства проверки и профилировщик.

Название Valgrind - это отсылка к главному входу в Валгаллу из скандинавской мифологии. Во время разработки (до релиза) проект получил название Heimdall ; однако имя могло бы конфликтовать с пакетом безопасности.

Обзор

Valgrind по сути является виртуальной машиной , используя только в срок (JIT) методы компиляции, включая динамическое перекомпиляции . Ничто из исходной программы никогда не запускается непосредственно на главном процессоре . Вместо этого Valgrind сначала переводит программу во временную, более простую форму, называемую промежуточным представлением (IR), которая не зависит от процессора и основана на SSA . После преобразования инструмент (см. Ниже) может выполнять любые преобразования в IR, прежде чем Valgrind переведет IR обратно в машинный код и позволит хост-процессору запустить его. Valgrind перекомпилирует двоичный код для работы на хосте и целевых (или смоделированных) процессорах одной архитектуры. Он также включает в себя заглушку GDB, позволяющую отлаживать целевую программу во время ее работы в Valgrind, с «командами монитора», которые позволяют запрашивать у инструмента Valgrind различную информацию.

При этих преобразованиях (и обычно коде, который вставляет инструмент) теряется значительная производительность; обычно код запускается с помощью Valgrind, а инструмент «none» (который ничего не делает с IR) работает на 20–25% скорости нормальной программы.

инструменты

Memcheck

В Valgrind входит несколько инструментов (и несколько внешних). Инструмент по умолчанию (и наиболее часто используемый) - Memcheck . Memcheck вставляет дополнительный инструментальный код почти во все инструкции, который отслеживает правильность (вся нераспределенная память запускается как недействительная или "неопределенная", пока она не будет инициализирована в детерминированное состояние, возможно, из другой памяти) и адресуемость (независимо от того, указан ли адрес памяти в вопрос указывает на выделенный, не освобожденный блок памяти), хранящийся в так называемых битах V и A соответственно. Когда данные перемещаются или обрабатываются, инструментальный код отслеживает биты A и V, поэтому они всегда верны на однобитовом уровне.

Кроме того, Memcheck заменяет стандартный распределитель памяти C своей собственной реализацией, которая также включает средства защиты памяти вокруг всех выделенных блоков (с битами A, установленными в «недействительный»). Эта функция позволяет Memcheck обнаруживать отдельные ошибки, когда программа читает или записывает небольшой объем вне выделенного блока. Memcheck может обнаружить и предупредить о следующих проблемах:

  • Использование неинициализированной памяти
  • Чтение / запись памяти после того, как это было free «D
  • Чтение / списание конца malloc блоков 'd
  • Утечки памяти

Цена этого - потеря производительности. Программы, работающие под Memcheck, обычно работают в 20–30 раз медленнее, чем за пределами Valgrind, и используют больше памяти (есть штраф памяти за выделение). Таким образом, немногие разработчики постоянно запускают свой код под Memcheck (или любым другим инструментом Valgrind). Чаще всего они используют такие инструменты либо для отслеживания какой-то конкретной ошибки, либо для проверки отсутствия скрытых ошибок (тех, которые может обнаружить Memcheck) в коде.

Прочие инструменты

Помимо Memcheck, у Valgrind есть еще несколько инструментов:

  • Нет , запускает код на виртуальной машине без выполнения какого-либо анализа и, таким образом, имеет минимально возможные накладные расходы на ЦП и память среди всех инструментов. Поскольку сам valgrind обеспечивает обратную трассировку после ошибки сегментации , инструмент none обеспечивает эту трассировку с минимальными издержками.
  • Addrcheck похож на Memcheck, но с гораздо меньшими накладными расходами на ЦП и память, что позволяет отлавливать меньше типов ошибок. Addrcheck удален с версии 3.2.0.
  • Массив , профайлер кучи . Отдельный GUI массив-визуализатор визуализирует вывод из Massif.
  • Helgrind и DRD , обнаруживают состояния гонки в многопоточном коде
  • Cachegrind , профилировщик кеша . Отдельный графический интерфейс KCacheGrind визуализирует вывод Cachegrind.
  • Callgrind , анализатор графа вызовов, созданный Йозефом Вайдендорфер, был добавлен в Valgrind с версии 3.2.0. KCacheGrind может визуализировать вывод Callgrind.
  • DHAT , инструмент динамического анализа кучи, который анализирует, сколько памяти выделено и как долго, а также шаблоны использования памяти.
  • exp-sgcheck ( до версии 3.7 назывался exp-ptrcheck ), экспериментальный инструмент для поиска ошибок переполнения стека и глобального массива, которые Memcheck не может найти. Некоторый код приводит к ложным срабатываниям этого инструмента.
  • exp-bbv , симулятор производительности, который экстраполирует производительность из небольшого набора образцов.

Также доступно несколько инструментов внешней разработки. Одним из таких инструментов является ThreadSanitizer, еще один детектор состояний гонки .

Поддерживаемые платформы

Начиная с версии 3.4.0, Valgrind поддерживает Linux на x86 , x86-64 и PowerPC . Поддержка OS X была добавлена ​​в версии 3.5.0. Поддержка Linux на ARMv7 (например, используется в некоторых смартфонах ) была добавлена ​​в версии 3.6.0. Поддержка Solaris была добавлена ​​в версии 3.11.0. Существуют неофициальные порты на другие UNIX-подобные платформы (например, FreeBSD , OpenBSD и NetBSD ). С версии 3.7.0 добавлена ​​поддержка платформы ARM / Android .

Начиная с версии 3.9.0 существует поддержка Linux на MIPS64 с прямым и обратным порядком байтов, для MIPS DSP ASE на MIPS32, для инструкций с десятичной плавающей запятой s390x , для инструкций POWER8 ( Power ISA 2.07 ), для инструкций Intel AVX2 , для расширений Intel Transactional Synchronization Extensions , как RTM, так и HLE, а также начальная поддержка аппаратной транзакционной памяти при POWER.

История и развитие

Он назван в честь главного входа в Валгаллу в скандинавской мифологии .

Первоначальным автором Valgrind является Джулиан Сьюард , который в 2006 году получил премию Google-O'Reilly Open Source Award за свою работу над Valgrind.

Несколько других также внесли значительный вклад, в том числе Cerion Armor-Brown, Джереми Фицхардинг, Том Хьюз, Николас Нетеркот, Пол Маккеррас, Дирк Мюллер, Барт Ван Аше, Йозеф Вайдендорфер и Роберт Уолш.

Он используется в ряде проектов на базе Linux.

Ограничения Memcheck

Помимо снижения производительности, важным ограничением Memcheck является его неспособность обнаруживать все случаи ошибок границ при использовании статических данных или данных, размещенных в стеке. Следующий код без проблем передаст инструмент Memcheck в Valgrind, несмотря на наличие ошибок, описанных в комментариях:

  int Static[5];
  
  int func(void)
  {
    int Stack[5];
  
    Static[5] = 0;  /* Error - Static[0] to Static[4] exist, Static[5] is out of bounds */
    Stack [5] = 0;  /* Error - Stack[0] to Stack[4] exist, Stack[5] is out of bounds */
    
    return 0;
  }

Экспериментальный инструмент valgrind exp-sgcheck был написан для устранения этого ограничения в Memcheck. Он обнаружит ошибки переполнения массива при условии, что первый доступ к массиву находится в границах массива. Обратите внимание, что exp-sgcheck не обнаружит переполнение массива в приведенном выше коде, поскольку первый доступ к массиву находится за пределами границ, но обнаружит ошибку переполнения массива в следующем коде.

  void func(void)
  {
    int i, Stack[5];

    for (i = 0; i <= 5; i++)
        Stack [i] = 0;        /* Within bounds for i=0..4, out of bounds error when i=5 */
  }

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

Смотрите также

Ноты

Рекомендации

внешние ссылки