AddressSanitizer

Обзор

Языки C и C++ являются мощными, но могут страдать от класса ошибок, влияющих на правильность программы и безопасность программы. Начиная с Visual Studio 2019 версии 16.9 компилятор Microsoft C/C++ (MSVC) и интегрированная среда разработки поддерживают AddressSanitizer санитеризатор. AddressSanitizer (ASan) — это технология компилятора и среды выполнения, которая обнаруживает множество трудно обнаруживаемых ошибок без ложных срабатываний:

Почему используйте AddressSanitizer

Используйте 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, выбрав Tools>Get Tools and Features. В программе установки Visual Studio выберите Изменить для уже установленной версии Visual Studio, чтобы перейти к следующему экрану.

Снимок экрана, на котором показан Visual Studio Installer с выделенным компонентом C++ AddressSanitizer в разделе «Необязательные».

Примечание.

Если вы запускаете Visual Studio в новом обновлении, но не установили ASan, при запуске кода возникает ошибка:

LNK1356: не удается найти библиотеку "clang_rt.asan_dynamic-i386.lib".

Используйте AddressSanitizer

Начните создавать исполняемые файлы с параметром компилятора /fsanitize=address с помощью любого из следующих распространенных методов разработки:

  • Сборки командной строки
  • Система проектов Visual Studio
  • Интеграция Visual Studio CMake

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

Корпорация Майкрософт рекомендует использовать AddressSanitizer в следующих трех стандартных рабочих процессах:

В этой статье рассматриваются сведения, необходимые для включения трех рабочих процессов, перечисленных ранее. Сведения относятся к реализации 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 скомпилируйте basic-global-overflow.cpp с помощью /fsanitize=address /Zi.

Снимок экрана: командная строка с командой cl basic-global-overflow.cpp /fsanitize=address /Zi.

При запуске результирующего basic-global-overflow.exe в командной строке создается отформатированный отчет об ошибке, который следует.

Рассмотрим наложенные красные коробки, которые выделяют семь ключевых элементов информации:

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

Красные выделения, от верхнего до нижнего

  1. Ошибка безопасности памяти — это переполнение глобального буфера.
  2. Существовало 4 байта (32 бита), хранящихся вне любой определяемой пользователем переменной.
  3. Операция записи произошла в функции main(), определенной в файле basic-global-overflow.cpp на 7 строке.
  4. Переменная с именем x определяется в basic-global-overflow.cpp в строке 3, начиная с столбца 8.
  5. Эта глобальная переменная x имеет размер 400 байт.
  6. Точный байт тени , описывающий адрес, предназначенный для хранилища, имел значение 0xf9.
  7. Согласно легенде теневого байта, 0xf9 — это область заполнения справа от int x[100].

Примечание.

Когда AddressSanitizer сообщает об ошибке, среда выполнения ASan вызывает символизатор LLVM для создания имен функций в стеке вызовов.

Использование AddressSanitizer в Visual Studio

AddressSanitizer интегрирован в среду разработки Visual Studio. Чтобы включить AddressSanitizer для проекта MSBuild, щелкните проект правой кнопкой мыши в Обозреватель решений и выберите "Свойства". В диалоговом окне "Страницы свойств" выберите Свойства конфигурации>>, а затем измените параметр Enable AddressSanitizer. Нажмите ОК, чтобы сохранить внесенные изменения.

Снимок экрана: диалоговое окно

Чтобы выполнить сборку из интегрированной среды разработки, отказаться от любых несовместимых параметров. Для существующего проекта, скомпилированного с помощью /Od (или режима отладки), может потребоваться отключить следующие параметры:

Чтобы создать и запустить отладчик, нажмите клавишу F5. В Visual Studio появляется окно "Исключение выброшено"

Снимок экрана отладчика, показывающий ошибку переполнения глобального буфера.

Использование AddressSanitizer с использованием Visual Studio: CMake

Чтобы включить AddressSanitizer для проекта CMake, созданного для целевой платформы Windows, выполните следующие действия:

  1. Откройте раскрывающееся меню "Конфигурации" на панели инструментов в верхней части интегрированной среды разработки и выберите пункт "Управление конфигурациями".

    Снимок экрана, на котором показано раскрывающееся меню конфигурации CMake с такими параметрами, как x64 Debug, x64 Release и, в нижней части списка, пункт Manage Configurations..., выделен.

    Это действие открывает редактор параметров CMake Project, который отражает содержимое файла CMakeSettings.json project.

  2. Выберите ссылку "Изменить JSON ". Этот выбор переключает представление на необработанный JSON.

  3. Чтобы включить AddressSanitizer, добавьте следующий фрагмент кода в предустановку "windows-base" внутри "configurePresets":.

    "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"
            }
          },
    
  4. 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>>")
    
  5. Используйте ctrl+S , чтобы сохранить этот JSON-файл.

  6. Очистите каталог кэша CMake и выполните перенастройку, выбрав в меню Visual Studio: Проект>Удалить кэш и Перенастроить. Нажмите кнопку "Да", когда появится запрос, чтобы очистить каталог кэша и перенастроить его.

  7. Замените содержимое исходного файла, например, 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;
    }
    
  8. Выберите F5 для повторной компиляции и запуска под отладчиком.

    Скриншот демонстрирует ошибку при сборке с использованием CMake.

    Снимок экрана, на котором показано исключение с сообщением: ошибка AddressSanitizer: переполнение глобального буфера.

Аварийные дампы AddressSanitizer

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

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

Чтобы создать файл дампа, который можно просмотреть в Visual Studio на другом компьютере позже:

set ASAN_SAVE_DUMPS=MyFileName.dmp

Начиная с Visual Studio 16.9, вы можете отобразить точно определённую ошибку, сохранённую в файле *.dmp, поверх исходного кода.

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

Примеры ошибок

AddressSanitizer может обнаружить несколько типов ошибок неправильного использования памяти. Ниже приведено множество ошибок среды выполнения при запуске двоичных файлов, скомпилированных с помощью параметра компилятора AddressSanitizer (/fsanitize=address).

Дополнительные сведения о примерах см. в разделе Примеры ошибок AddressSanitizer.

Различия с Clang 12.0

В настоящее время MSVC отличается от Clang 12.0 в двух функциональных областях:

  • stack-use-after-scope: этот параметр включен по умолчанию и не может быть отключен.
  • stack-use-after-return: эта возможность требует дополнительного параметра компилятора и недоступна, если задан только ASAN_OPTIONS.

Эти решения были приняты для уменьшения матрицы тестов, необходимой для доставки этой первой версии.

Функции, которые могут привести к ложным срабатываниям в Visual Studio 2019 16.9, не были включены. Эта дисциплина обеспечивает поддержание целостности тестирования, необходимой при рассмотрении совместимости с десятилетиями существующего кода. Дополнительные возможности можно рассмотреть в последующих выпусках:

Дополнительные сведения см. в разделе "Создание для AddressSanitizer" с помощью MSVC.

Документация по отрасли

Обширная документация существует для этих языковых и зависимых от платформ реализаций технологии AddressSanitizer.

В этой основополагающей статье о AddressSanitizer (external) описывается реализация.

См. также