MemorySanitizer
MemorySanitizer (сокращённо MSan) — это инструмент динамического анализа кода, предназначенный для обнаружения ошибок, связанных с использованием неинициализированной памяти в программах на языках C, C++ и других, компилируемых с помощью Clang/LLVM. MSan работает на этапе выполнения программы, отслеживая состояние каждой ячейки памяти и сигнализируя о попытках чтения данных, которые не были предварительно записаны.
Принцип работы
MemorySanitizer основан на инструментировании кода на стадии компиляции. Компилятор Clang вставляет в скомпилированный бинарный файл дополнительные проверки для каждой операции чтения памяти. Для отслеживания состояния памяти используется специальная «теневая память» (shadow memory), которая хранит метаданные о каждой ячейке основной памяти.
Теневая память
Каждому байту основной памяти ставится в соответствие один или несколько битов в теневой памяти, которые кодируют его состояние:
- 0 — память полностью инициализирована (содержит корректные данные).
- 1 — память неинициализирована (содержит «мусор»).
При выполнении операции чтения MSan проверяет состояние соответствующей ячейки теневой памяти. Если она помечена как неинициализированная, генерируется сообщение об ошибке с указанием точного места в исходном коде (файл, строка, стек вызовов).
Отслеживание через инструкции
MSan обрабатывает все инструкции, работающие с памятью: загрузки (load), сохранения (store), вызовы функций, операции с указателями и т.д. Для каждой инструкции генерируется код, который:
- Считывает значение из теневой памяти.
- Если значение не равно нулю — вызывает обработчик ошибки.
- После записи в память обновляет теневую память, помечая ячейки как инициализированные.
История
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 →