Санитайзеры

Санитайзеры – инструменты отладки, позволяющие проводить более продвинутые анализы во время исполнения программного обеспечения. Компилятор Clang (фронтенд LLVM) поддерживает шесть видов санитайзеров:

  • AddressSanitizer – детектор ошибок при работе с адресацией (выход за границы выделенной области памяти, стека, двойное высвобождение памяти и другое).

  • ThreadSanitizer – детектор ошибок при взаимодействиями между потоками (data race).

  • UndefinedBehaviorSanitizer – детектор специфических ошибок, чаще всего регламентированных в стандарте как Undefined Behavior.

  • MemorySanitizer – детектор чтения из неинициализированной области памяти.

  • LeakSanitizer – детектор утечки (не освобождаемой) памяти.

  • DataFlowSanitizer – обобщенный анализ потока данных.

Все виды детекторов совместить нельзя. Можете попробовать проанализировать код всеми видами санитайзеров, однако нас будет интересовать только: ASan, UBSan и LSan – почти всегда достаточный набор для диагностики кода.

Чтобы собрать программу с таким набором санитайзеров, необходимо установить флаг -fsanitize с желаемыми детекторами, и, обязательно, выбрать сборку под отладчиком:

clang -O0 -g -fno-sanitize-recover=all -fsanitize=address,undefined,leak main.c -o main.exe

Примечание: на MacOS без leak – по документации, address уже включает обнаружение утечки памяти

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

Настройка окружения

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

Windows

Возможности даже при большом желании использования интересных нам санитайзеров через легальные схемы на операционной системе Windows через нативный (то есть тот, который ожидается) MSVC или clang-cl не получится. Для решения этой проблемы предлагается два варианта: использование подсистемы Linux для Windows (WSL, должна быть поддержка Hyper-V) и использование виртуальной машины VirtualBox (медленнее, но никаких требований от вашего железа не требуется).

Нативный метод

Как уже сказано, на MSVC и clang-cl поддерживают только AddressSanitizer. Тем не менее, это может быть полезно, если у вас внезапная поломка программы на ровном месте. Для компиляции необходимо подать соответствующий флаг и отладочную информацию: рекомендуется использовать полную статистику, то есть, /Z7.

cl.exe /Od /Z7 /fsanitize=address main.c

Более информации здесь.

WSL

В качестве дистрибутива рассмотрим самый простой и рекомендуемый для всех новичков в Линукс – Ubuntu.

  1. Активируйте компоненты Windows.

    • Откройте Панель управленияВсе элементы панели управленияПрограммы и компонентыВключение и отключение компонентов Windows.

    • В списке найдите пункт Подсистема Windows для Linux и убедитесь, что перед пунктом стоит галочка. В ином случае: поставьте, сохраните изменения и перезагрузите компьютер.

  2. В Microsoft Store установите приложение Подсистема Windows для Linux.

  3. Запустите терминал/командную строку (далее – терминал), введите следующее ниже и перезагрузите компьютер:

    wsl.exe --update
    wsl.exe --set-default-version 2

    По пути домашнего каталога текущего пользователя должен появиться файл .wslconfig, в котором лежат основные глобальные настройки для WSL2. Содержимое .wslconfig предлагается установить следующим:

    [wsl2]
    nestedVirtualization=true
    memory=2048MB
    processors=2

    Первые две строки должны быть по умолчанию после установки версии WSL на 2. Значение memory ограничивает подсистеме использование оперативной памяти, processors, соответственно, на количество процессоров.

  4. Запустите терминал и установите Ubuntu 22.04.3 LTS с помощью следующей команды:

    wsl.exe --install Ubuntu-22.04

    Альтернативный вариант: установить приложение с Microsoft Store.

  5. Запустите дистрибутив (это можно сделать, введя в терминал wsl), проследуйте инструкциям установки. Введите в терминал WSL:

   sudo apt-get update && sudo apt-get upgrade -y # обновление пакетов  
   sudo apt-get install build-essential libc++-dev libc++abi-dev binutils binutils-dev clang gdb pkg-config    

Альтернатива – программа valgrind. Введите в терминал WSL:

Установка valgrind:

sudo apt-get install -y valgrind

Компиляция с valgrind:

clang -O0 -gdwarf-4 main.c -o main.exe      

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

Запуск с valgrind:

valgrind --tool=memcheck --gen-suppressions=all --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./main.exe      

VirtualBox

Данная часть ничем не отличается от главы про WSL, кроме установки и настройки системы.

  1. Скачайте и установите VirtualBox и образ диска Ubuntu Server. Если хватает ресурсов, можно скачать пользовательскую версию Ubuntu Desktop.

  2. Установите операционную систему Ubuntu Server.

    1. Создайте новую машину, New.

      • В поле Name введите имя машины, например, SanitizerRunner.

      • В поле Type выберите тип Linux.

      • В поле Version выставите Ubuntu (64-bit) или Ubuntu (32-bit).

    2. Далее нажимаете всё время Next. Из интересного стоит отметить количество места для операционной системы – хватает и 10 ГБ (утверждается, что можно поставить чуть поменьше). Также, по умолчанию, на ОС будет приходиться 2 ГБ оперативной памяти.

    3. Настройте виртуальную машину, Settings. В разделе Storage, в Empty нажмите на значок дискаChoose a disk file – выберите скачанный .iso.

    4. Запустите виртуальную машину, Start. В разделе Guided storage configuration рекомендуется убрать пункт Set up this disk as an LVM group.

    5. Во всех оставшихся разделах нажимаете всё время Next, создайте пользователя и ничего лишнего не выбирайте для экономия места и времени.

    В случае с Ubuntu Desktop потребуется 20 ГБ и 4 ГБ оперативной памяти (рекомендация), установка более очевидная из-за графического интерфейса. Рекомендуется в разделе Updates and other software:

    • Выбрать Minimal installation.

    • В пункте Other options: выбрать Download updates while installing Ubuntu и Install third-party software for graphics and Wi-Fi hardware and additional media formats.

    В дальнейшем все действия на серверной версии не будут отличаться от пользовательской.

  3. Дальнейшие шаги ничем не отличаются от шага 5 из пункта про WSL.

Для более удобной работы с виртуальной машиной рекомендуется прочитать в Интернете про SSH подключения в локальной сети.

Linux

Данная инструкция целиком и полностью копирует последовательность действий рассмотренных выше WSL и VirtualBox. Обратите внимание, что в разных дистрибутивах названия тех или иных пакетов могут отличаться.

MacOS

С MacOS как и в случае с Windows с санитайзерами всё довольно грустно и печально, если хочется компилировать с терминала. В качестве решений данной проблемы могут послужить:

Использование виртуальной машины. В случае платформы ARM, в UTM выбираете пункт emulate. Если ваш Mac поддерживает VirtualBox и имеет возможность запустить виртуальную машину с образом Ubuntu, тогда вам следует обратиться к этому пункту.

Нативные компиляторы и приложения. В этом случае устанавливаете все необходимые для работы компилятора Clang через пакетный менеджер brew компилируетесь через терминал (clang из Homebrew):

/path/to/homebrew/clang -O0 -g -fno-sanitize-recover=all -fsanitize=address,undefined main.c -o main.exe

и запускаетесь с:

ASAN_OPTIONS=verbosity=1:detect_leaks=1 ./main.exe

либо используйте Xcode в качестве средства разработки и запуска санитайзеров.

Last updated