Использование дезинфицирующих средств (sanitizers)

Что такое дезинфицирующие средства?

Sanitizers — это инструменты статического инструментирования, помогающие находить ошибки, которые традиционные отладчики обычно не могут обнаружить. Это особенно полезно в сочетании с Модульное тестирование в непрерывной интеграции.

Санитайзеры можно использовать в Windows, macOS и Linux с помощью компиляторов Clang (LLVM), GCC или Visual Studio. Некоторые платформы также могут иметь собственные санитайзеры. Если один и тот же санитайзер предоставляется несколькими разными компиляторами, помните, что их вывод и поведение будут немного различаться.

Использование дезинфицирующих средств на Godot

Санитайзеры требуют перекомпиляции исполняемого файла. Это означает, что вы не сможете использовать официальные исполняемые файлы Godot для запуска санитайзеров.

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

Это влияет на производительность, поскольку требуется выполнение множества дополнительных проверок во время выполнения. Также увеличивается использование памяти. В одной сборке можно использовать определённые комбинации нескольких санитайзеров. Однако следует учитывать влияние на производительность при одновременном использовании нескольких санитайзеров, поскольку результирующий двоичный файл может быть чрезмерно медленным.

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

Адрес дезинфицирующего средства (ASAN)

Санитайзер адресов, как правило, используется чаще всего. Он может диагностировать такие проблемы, как переполнение буфера и доступ за пределы допустимого диапазона. Если движок аварийно завершает работу с сообщением типа free(): invalid pointer, это обычно означает переполнение буфера. (Это сообщение выводится средой выполнения C, а не Godot.)

В некоторых ситуациях (например, при обнаружении неинициализированных чтений памяти) средства очистки адресов недостаточно. Вместо него следует использовать Очиститель памяти (MSAN).

Также можно обнаружить ситуации использования после возврата, указав переменную окружения ASAN_OPTIONS=detect_stack_use_after_return=1 перед запуском Godot (а не при его компиляции). Это увеличивает нагрузку на функцию очистки адресов во время выполнения, поэтому включайте эту функцию только тогда, когда она действительно нужна.

Чтобы включить функцию очистки адресов в сборке Godot, передайте параметр use_asan=yes SCons при компиляции. Включение ASAN обычно замедляет работу двоичного файла примерно в два раза.

Предупреждение

Из-за проектного решения, санитайзеры адресов, памяти и потоков являются взаимоисключающими. Это означает, что в данном исполняемом файле можно использовать только один из этих санитайзеров.

Средство для дезинфекции утечек (LSAN)

Утилита очистки утечек может обнаруживать утечки памяти, то есть ситуации, когда неиспользуемая память не освобождается запущенной программой. Это может привести к нехватке памяти, если программа работает достаточно долго. Поскольку Godot может работать на выделенных серверах месяцами или даже годами без перезапуска, важно устранять утечки памяти по мере их возникновения.

Чтобы включить средство очистки утечек в сборке Godot, передайте параметр use_lsan=yes SCons при компиляции. Включение LSAN лишь немного снижает производительность, но программа будет завершаться гораздо медленнее, поскольку обнаружение утечек происходит при выходе из программы.

Очиститель памяти (MSAN)

Санитайзер памяти дополняет Адрес дезинфицирующего средства (ASAN). В отличие от дезинфицирующего средства адресов, дезинфицирующее средство памяти может обнаруживать неинициализированные чтения памяти.

Чтобы включить очиститель памяти в сборке Godot, передайте параметр use_msan=yes SCons при компиляции. Включение MSAN обычно замедляет работу двоичного файла примерно в 3 раза.

Предупреждение

Из-за проектного решения, санитайзеры адресов, памяти и потоков являются взаимоисключающими. Это означает, что в данном исполняемом файле можно использовать только один из этих санитайзеров.

Дезинфицирующее средство thread (TSAN)

Фильтр потоков используется для отслеживания состояний гонки, связанных с многопоточностью. Состояние гонки возникает, когда несколько потоков пытаются одновременно изменить одни и те же данные. Поскольку операционная система может упорядочить планирование потоков любым способом, это приводит к некорректному поведению, которое проявляется лишь изредка (и, как следствие, его сложно отслеживать). Чтобы предотвратить состояние гонки, необходимо добавить блокировку, которая гарантирует, что только один поток сможет получить доступ к общим данным в определённый момент времени.

Чтобы включить функцию очистки потоков в сборке Godot, передайте параметр use_tsan=yes SCons при компиляции. Включение TSAN обычно замедляет работу двоичного кода в 10 раз, а также увеличивает потребление памяти примерно в 8 раз.

Предупреждение

Из-за проектного решения, санитайзеры адресов, памяти и потоков являются взаимоисключающими. Это означает, что в данном исполняемом файле можно использовать только один из этих санитайзеров.

Примечание

В Linux, если вы столкнулись со следующей ошибкой:

FATAL: ThreadSanitizer: неожиданное отображение памяти

Вам может потребоваться временно снизить энтропию Рандомизации Адресного Пространства (ASLR) в вашей системе с помощью:

sudo sysctl vm.mmap_rnd_bits=28

Или, что предпочтительнее, полностью отключите её с помощью:

sudo sysctl kernel.randomize_va_space=0

И как только вы закончите с дезинфектором потоков, увеличьте энтропию ASLR с помощью:

sudo sysctl vm.mmap_rnd_bits=32

Или повторно включите ASLR с помощью:

sudo sysctl kernel.randomize_va_space=2

Перезагрузка компьютера также вернет состояние ASLR к значениям по умолчанию.

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

Дезинфицирующее средство неопределенного поведения (UBSAN)

Фильтр неопределённого поведения используется для отслеживания ситуаций, в которых программа демонстрирует случайное и непредсказуемое поведение. Это происходит из-за кода C/C++, который принимается компилятором, но не является корректным. Компиляция с другим набором оптимизаций также может изменить наблюдаемые результаты неопределённого поведения.

Чтобы включить функцию очистки неопределённого поведения в сборке Godot, передайте параметр use_ubsan=yes SCons при компиляции. Включение UBSAN приводит лишь к небольшому снижению производительности.

Дезинфицирующие средства для конкретных платформ

Web

При компиляции для Web доступны 2 дополнительных параметра scons-дезинфектора:

  • use_assertions=yes включает утверждения Emscripten во время выполнения, которые могут выявлять различные проблемы.

  • use_safe_heap=yes включает дезинфицирующее средство SAFE_HEAP от Emscripten. Оно обеспечивает схожую с ASAN функциональность, но фокусируется на проблемах, характерных для WebAssembly. Совместимость SAFE_HEAP с ASAN и UBSAN в одном исполняемом файле не гарантируется, поэтому может потребоваться его отдельная сборка.