Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Обзор
Языки C и C++ являются мощными, но могут страдать от класса ошибок, влияющих на правильность программы и безопасность программы. Начиная с Visual Studio 2019 версии 16.9 компилятор Microsoft C/C++ (MSVC) и интегрированная среда разработки поддерживает санитизатор AddressSanitizer . AddressSanitizer (ASan) — это технология компилятора и среды выполнения, которая обнаруживает множество трудно обнаруживаемых ошибок без ложных срабатываний:
-
Несоответствия (alloc/dealloc) и /
deleteнесоответствия типов - Выделения слишком большие для кучи
-
callocпереполнение иallocaпереполнение - Двойное освобождение и использование после освобождения
- Переполнение глобальной переменной
- Переполнение буфера кучи
- Недопустимое выравнивание выровненных значений
-
memcpyиstrncatперекрытие параметров - Переполнение буфера стека и недостаточное заполнение
-
Использование стека после
returnи использование после выхода из области видимости - Использование памяти после её заражения
Используйте AddressSanitizer, чтобы сократить время, затраченное на:
- Базовая правильность
- Переносимость кроссплатформенных платформ
- Безопасность
- Стресс-тестирование
- Интеграция нового кода
AddressSanitizer, первоначально представленный Google, предоставляет технологии обнаружения ошибок во время выполнения, которые используют существующие системы сборки и существующие тестовые ресурсы напрямую.
AddressSanitizer интегрирован с системой проектов Visual Studio, системой сборки CMake и интегрированной среды разработки. Проекты могут включить AddressSanitizer, задав свойство проекта или используя один дополнительный параметр компилятора: /fsanitize=address Новый параметр совместим со всеми уровнями оптимизации и конфигурации x86 и x64. Однако он не совместим с изменением и продолжением, добавочным связыванием и /RTC.
Начиная с Visual Studio 2019 версии 16.9 технология AddressSanitizer Майкрософт обеспечивает интеграцию с интегрированной средой разработки Visual Studio. Функционал может по желанию создавать файл аварийного дампа при обнаружении ошибки во время выполнения. Если вы устанавливаете переменную среды перед запуском ASAN_SAVE_DUMPS=MyFileName.dmp программы, файл аварийного дампа создается с дополнительными метаданными для эффективной отладки точно диагностированных ошибок. Эти файлы дампа облегчают расширенное использование AddressSanitizer для:
- Тестирование локального компьютера
- Локальное распределенное тестирование
- Облачные рабочие процессы для тестирования
Установка AddressSanitizer
Процессы C++ в установщике Visual Studio по умолчанию устанавливают библиотеки AddressSanitizer и интеграцию с интегрированной средой разработки. Однако если вы обновляете более раннюю версию Visual Studio 2019, используйте установщик, чтобы включить поддержку ASan после обновления. Установщик можно открыть в главном меню Visual Studio через Средства>Получить средства и компоненты... Выберите Изменить на существующей установке Visual Studio через Visual Studio Installer, чтобы перейти к следующему экрану.
Примечание.
Если вы запускаете Visual Studio в новом обновлении, но не установили ASan, при запуске кода появится сообщение об ошибке:
LNK1356: не удается найти библиотеку "clang_rt.asan_dynamic-i386.lib".
Используйте AddressSanitizer
Начните создавать исполняемые файлы с параметром компилятора /fsanitize=address с помощью любого из следующих распространенных методов разработки:
- Сборки командной строки
- Система проектов Visual Studio
- Интеграция Visual Studio CMake
Перекомпилируйте, а затем обычно запустите программу. Генерация этого кода выявляет множество типов точно диагностированных ошибок. Эти ошибки передаются тремя способами: в среде отладки в IDE, через командную строку или в новом типе файла дампа для точной обработки в автономном режиме.
Корпорация Майкрософт рекомендует использовать AddressSanitizer в следующих трех стандартных рабочих процессах:
Внутренний цикл разработчика
- Visual Studio — командная строка
- Visual Studio — система проектов
- Visual Studio — CMake
CI/CD — непрерывная интеграция / непрерывная разработка
- Отчеты об ошибках — новые файлы дампа AddressSanitizer
Фаззинг - построение с использованием оболочки libFuzzer
- Azure OneFuzz
- Локальный компьютер
В этой статье рассматриваются сведения, необходимые для включения трех рабочих процессов, перечисленных ранее. Сведения относятся к реализации AddressSanitizer, зависящей от платформы Windows 10 (и более поздних версий). Эта документация дополняет отличную документацию от Google, Apple и GCC , уже опубликованных.
Примечание.
Поддержка ограничена x86 и x64 в Windows 10 и более поздних версий.
Отправьте нам отзыв о том, что вы хотите увидеть в будущих выпусках. Ваши отзывы помогают нам определять приоритеты других санитизаторов в будущем, таких как /fsanitize=thread, , /fsanitize=leak/fsanitize=memoryили /fsanitize=undefined/fsanitize=hwaddress. При возникновении проблем можно сообщить об ошибках .
Использование AddressSanitizer из командной строки разработчика
/fsanitize=address Используйте параметр компилятора в командной строкеразработчика, чтобы включить компиляцию для среды выполнения AddressSanitizer. Параметр /fsanitize=address совместим с существующими уровнями оптимизации C++ или C (например, /Od, /O1, /O2и /O2 /GL). Опция работает со статическими и динамическими CRT (например, /MD, /MDd, /MT, и /MTd). Он работает независимо от того, создаете ли файл EXE или библиотеку DLL. Сведения об отладке необходимы для оптимального форматирования стеков вызовов. В следующем примере cl /fsanitize=address /Zi передается в командной строке.
Примечание.
AddressSanitizer не поддерживает оптимизацию на основе профилей (PGO). AddressSanitizer не следует использовать в рабочей среде.
Библиотеки AddressSanitizer (.lib файлы) подключаются для вас автоматически. Дополнительные сведения см. в справочнике по AddressSanitizer: языку, сборке и отладке.
Пример: глобальное базовое переполнение буфера
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Используя командную строку разработчика для Visual Studio 2019, скомпилируйте main.cpp с помощью /fsanitize=address /Zi
При запуске результирующего main.exe в командной строке создается отформатированный отчет об ошибке, который следует.
Рассмотрим наложенные красные коробки, которые выделяют семь ключевых элементов информации:
В отчете об ошибке есть семь красных выделений, определяющих ключевые фрагменты информации. Они связаны с нумерованным списком, который следует на этом снимке экрана. Нумерованные поля выделяют следующий текст: 1) global-buffer-overflow 2) WRITE размером 4 3) basic-global-overflow.cpp 7 4) справа от глобальной переменной x, определенной в области условных обозначений basic-global-overflow.cpp:3:8) размером 400 6) 00 00[f9]f9 f9 7) Box находится в области условных обозначений тени байтов и содержит глобальную красную зону: f9
Красные выделения, от верхнего до нижнего
- Ошибка безопасности памяти — это переполнение глобального буфера.
- Существовало 4 байта (32 бита), хранящихся вне любой определяемой пользователем переменной.
- Операция записи произошла в функции
main(), определенной в файлеbasic-global-overflow.cppна 7 строке. - Переменная с именем
xопределяется в basic-global-overflow.cpp в строке 3, начиная с столбца 8 - Эта глобальная переменная
xимеет размер 400 байт - Точный теневой байт, описывающий адрес, ориентированный на магазин, имел значение
0xf9 - Согласно легенде о теневых байтах,
0xf9является областью заполнения справа отint x[100].
Примечание.
Имена функций в стеке вызовов создаются с помощью символа LLVM, вызываемого средой выполнения при ошибке.
Использование AddressSanitizer в Visual Studio
AddressSanitizer интегрирован в среду разработки Visual Studio. Чтобы включить AddressSanitizer для проекта MSBuild, щелкните проект правой кнопкой мыши в Обозреватель решений и выберите "Свойства". В диалоговом окне "Страницы свойств" выберите Свойства конфигурации>C/C++>Общие сведения, а затем измените параметр Enable AddressSanitizer. Нажмите ОК, чтобы сохранить внесенные изменения.
Чтобы выполнить сборку из интегрированной среды разработки, отказаться от любых несовместимых параметров. Для существующего проекта, скомпилированного с помощью /Od (или режима отладки), может потребоваться отключить следующие параметры:
-
/ZIОтключение (формат сведений отладки) -
/RTC1Выключите (проверки среды выполнения) -
/INCREMENTALОтключить (добавочное связывание)
Чтобы создать и запустить отладчик, нажмите клавишу F5. В Visual Studio появляется окно "Исключение выброшено"
Использование AddressSanitizer с использованием Visual Studio: CMake
Чтобы включить AddressSanitizer для проекта CMake, созданного для целевой платформы Windows, выполните следующие действия:
Откройте раскрывающийся список "Конфигурации" на панели инструментов в верхней части интегрированной среды разработки и выберите пункт "Управление конфигурациями".
Откроется редактор параметров проекта CMake, который отражает содержимое файла проекта
CMakeSettings.json.Выберите ссылку "Изменить JSON " в редакторе. Этот выбор переключает представление на необработанный JSON.
Добавьте следующий фрагмент кода в
"windows-base"предустановку, внутри"configurePresets":чтобы включить AddressSanitizer."environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }"configurePresets"выглядит примерно так, после этого:"configurePresets": [ { "name": "windows-base", "hidden": true, "generator": "Ninja", "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe" }, "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" }, "environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" } },AddressSanitizer не работает, если указан параметр edit-and-continue (
/ZI), который включен по умолчанию для новых проектов CMake. ВCMakeLists.txt, оставьте комментарий (добавьте префикс#) к строке, начинающейся сset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT". Эта строка выглядит примерно так, после этого:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")Введите CTRL+S , чтобы сохранить этот JSON-файл
Очистите каталог кэша CMake и выполните перенастройку, выбрав в меню Visual Studio: Проект>Удалить кэш и Перенастроить. Нажмите кнопку "Да", когда появится запрос, чтобы очистить каталог кэша и перенастроить его.
Замените содержимое исходного файла (например,
CMakeProject1.cppна следующее:// CMakeProject1.cpp : Defines the entry point for the application #include <stdio.h> int x[100]; int main() { printf("Hello!\n"); x[100] = 5; // Boom! return 0; }Выберите F5 для повторной компиляции и запуска под отладчиком.
Скриншот демонстрирует ошибку при сборке с использованием CMake.
Аварийные дампы AddressSanitizer
Мы представили новые функции в AddressSanitizer для использования с облачными и распределенными рабочими процессами. Эта функция позволяет в автономном режиме просматривать ошибку AddressSanitizer в интегрированной среде разработки. Ошибка отображается поверх вашего исходного кода, так же как и в интерактивном сеансе отладки.
Эти новые файлы дампа могут привести к эффективности при анализе ошибки. Вам не нужно повторно запускать или находить удаленные данные или искать компьютер, который был отключен.
Чтобы создать новый тип файла дампа, который можно просмотреть в Visual Studio на другом компьютере позже:
set ASAN_SAVE_DUMPS=MyFileName.dmp
Начиная с Visual Studio 16.9, вы можете отобразить точно диагностированную ошибку, хранящуюся в *.dmp файле, в верхней части исходного кода.
Эта новая функция аварийного дампа обеспечивает облачные рабочие процессы или распределенное тестирование. Его также можно использовать для регистрации подробной ошибки, подлежащей исправлению, в любой ситуации.
Примеры ошибок
AddressSanitizer может обнаружить несколько типов ошибок неправильного использования памяти. Ниже приведено множество ошибок среды выполнения при запуске двоичных файлов, скомпилированных с помощью параметра компилятора AddressSanitizer (/fsanitize=address).
alloc-dealloc-mismatchallocation-size-too-bigcalloc-overflowdouble-freedynamic-stack-buffer-overflowglobal-buffer-overflowheap-buffer-overflowheap-use-after-freeinvalid-allocation-alignmentmemcpy-param-overlapnew-delete-type-mismatchstack-buffer-overflowstack-buffer-underflowstack-use-after-returnstack-use-after-scopestrncat-param-overlapuse-after-poison
Дополнительные сведения о примерах см. в разделе Примеры ошибок AddressSanitizer.
Различия с Clang 12.0
В настоящее время MSVC отличается от Clang 12.0 в двух функциональных областях:
- stack-use-after-scope — этот параметр включен по умолчанию и не может быть отключен.
-
стек-use-after-return — эта функция требует дополнительного параметра компилятора и не доступна только параметром
ASAN_OPTIONS.
Эти решения были приняты для уменьшения матрицы тестов, необходимой для доставки этой первой версии.
Функции, которые могут привести к ложным срабатываниям в Visual Studio 2019 16.9, не были включены. Эта дисциплина обеспечивает поддержание целостности тестирования, необходимой при рассмотрении совместимости с десятилетиями существующего кода. Дополнительные возможности можно рассмотреть в последующих выпусках:
- Порядок инициализации Fiasco
- Внутриобъектное переполнение
- Переполнение контейнера
- Вычитание/сравнение указателей
Дополнительные сведения см. в разделе "Создание для AddressSanitizer" с помощью MSVC.
Существующая документация отрасли
Обширная документация уже существует для этих языковых и зависимых от платформ реализаций технологии AddressSanitizer.
В этой основополагающей статье о AddressSanitizer (external) описывается реализация.
См. также
Известные проблемы AddressSanitizer
Справочник по сборке и языку AddressSanitizer
Справочник по среде выполнения AddressSanitizer
Теневые байты AddressSanitizer
Облачное или распределенное тестирование AddressSanitizer
Интеграция отладчика AddressSanitizer
Примеры ошибок AddressSanitizer