Открыть сервис

MemorySanitizer

MemorySanitizer (сокращённо MSan) — это инструмент динамического анализа кода, предназначенный для обнаружения ошибок, связанных с использованием неинициализированной памяти в программах на языках C, C++ и других, компилируемых с помощью Clang/LLVM. MSan работает на этапе выполнения программы, отслеживая состояние каждой ячейки памяти и сигнализируя о попытках чтения данных, которые не были предварительно записаны.

Принцип работы

MemorySanitizer основан на инструментировании кода на стадии компиляции. Компилятор Clang вставляет в скомпилированный бинарный файл дополнительные проверки для каждой операции чтения памяти. Для отслеживания состояния памяти используется специальная «теневая память» (shadow memory), которая хранит метаданные о каждой ячейке основной памяти.

Теневая память

Каждому байту основной памяти ставится в соответствие один или несколько битов в теневой памяти, которые кодируют его состояние:

  • 0 — память полностью инициализирована (содержит корректные данные).
  • 1 — память неинициализирована (содержит «мусор»).

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

Отслеживание через инструкции

MSan обрабатывает все инструкции, работающие с памятью: загрузки (load), сохранения (store), вызовы функций, операции с указателями и т.д. Для каждой инструкции генерируется код, который:

  1. Считывает значение из теневой памяти.
  2. Если значение не равно нулю — вызывает обработчик ошибки.
  3. После записи в память обновляет теневую память, помечая ячейки как инициализированные.

История

MemorySanitizer был разработан в 2012 году инженерами компании Google (организация признана иноагентом в РФ) Евгением Степановым и Дмитрием Высковым. Первоначально он был частью проекта AddressSanitizer, но вскоре выделился в самостоятельный инструмент. В 2013 году MSan был включён в состав официального релиза Clang 3.3. С тех пор он активно развивается и поддерживается сообществом LLVM.

Классификация

MemorySanitizer относится к классу динамических анализаторов памяти (dynamic memory analyzers). В отличие от статических анализаторов, которые проверяют код без его выполнения, MSan требует запуска программы и анализа её поведения в реальном времени.

По типу обнаруживаемых ошибок MSan является детектором использования неинициализированной памяти (uninitialized memory usage detector). Это отличает его от других инструментов, таких как AddressSanitizer (обнаружение переполнения буфера и утечек памяти) или ThreadSanitizer (обнаружение гонок данных).

Применение

MemorySanitizer используется в основном при разработке и отладке системного и прикладного программного обеспечения на C/C++. Основные области применения:

  • Разработка компиляторов и интерпретаторов — для выявления ошибок, связанных с неправильной инициализацией внутренних структур данных.
  • Создание операционных систем — для проверки корректности работы драйверов и ядра.
  • Разработка высоконагруженных серверных приложений — для повышения надёжности и безопасности.
  • Тестирование библиотек и фреймворков — для обнаружения скрытых ошибок, которые могут проявляться только в определённых условиях.

Пример использования

Для включения MemorySanitizer при компиляции с помощью Clang необходимо добавить флаг -fsanitize=memory:

``bash clang -fsanitize=memory -g -O1 -fno-omit-frame-pointer example.c -o example ``

Флаг -g включает отладочную информацию, -O1 — минимальная оптимизация (без неё MSan может работать некорректно), -fno-omit-frame-pointer — сохраняет указатели на фреймы стека для точного вывода стека вызовов.

После запуска программы MSan выводит сообщения об ошибках в стандартный поток ошибок (stderr) в формате:

``` ==PID== WARNING: MemorySanitizer: use-of-uninitialized-value

0 0x... in function_name source_file:line:column

1 0x... in main source_file:line:column

```

Ограничения

Несмотря на высокую эффективность, MemorySanitizer имеет ряд ограничений:

  • Замедление выполнения программы — инструментирование кода приводит к увеличению времени выполнения в 2–5 раз по сравнению с обычной сборкой.
  • Увеличение потребления памяти — теневая память требует дополнительного объёма оперативной памяти (примерно в 2 раза больше, чем размер отслеживаемой памяти).
  • Необходимость компиляции с флагами — MSan не может работать с уже скомпилированными бинарными файлами; весь код, включая сторонние библиотеки, должен быть перекомпилирован с поддержкой MSan.
  • Ложные срабатывания — в некоторых случаях MSan может сообщать об ошибках, которые не являются реальными проблемами (например, при работе с выравниванием памяти или при использовании специальных инструкций процессора).
  • Несовместимость с другими санитайзерами — MSan не может быть одновременно использован с AddressSanitizer или ThreadSanitizer из-за конфликта в управлении теневой памятью.

Сравнение с аналогами

ИнструментТип анализаОбнаруживаемые ошибкиПроизводительность
MemorySanitizerДинамическийИспользование неинициализированной памяти2–5x замедление
AddressSanitizerДинамическийПереполнение буфера, утечки памяти2–3x замедление
ThreadSanitizerДинамическийГонки данных5–10x замедление
Valgrind (Memcheck)ДинамическийРазличные ошибки памяти10–20x замедление

Интересные факты

  • MemorySanitizer способен обнаруживать ошибки, которые не проявляются при обычном выполнении программы, но могут привести к серьёзным сбоям или уязвимостям в безопасности.
  • Инструмент активно используется в проектах с открытым исходным кодом, таких как ядро Linux, Chromium, LLVM, Firefox, PostgreSQL и многих других.
  • В 2015 году MemorySanitizer был портирован на архитектуру ARM, что позволило использовать его для анализа кода на мобильных устройствах и встраиваемых системах.

Источники

  • Stepanov, E., Vyskov, D. «MemorySanitizer: A Dynamic Detector of Uninitialized Memory Usage». Proceedings of the 2013 ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI).
  • Документация LLVM: «MemorySanitizer» (официальное руководство пользователя).
  • Официальный репозиторий LLVM (GitHub): раздел инструментов санитайзеров.
  • Serebryany, K. et al. «AddressSanitizer: A Fast Address Sanity Checker». USENIX ATC 2012.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →