Поделиться через


AddressSanitizer

Обзор

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

Используйте 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, чтобы открыть следующий экран.

Снимок экрана: установщик Visual Studio. Компонент C++ AddressSanitizer в разделе

Примечание.

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

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

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

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

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

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

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

В этой статье рассматриваются сведения, необходимые для включения трех рабочих процессов, перечисленных ранее. Сведения относятся к реализации AddressSanitizer, зависящей от платформы (и более поздних версий). Эта документация дополняет отличную документацию от 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и ).PGO Параметр работает со статическими и динамическими crT (например, , /MD, /MT/MDdи /MTd). Он работает независимо от того, создаете ли файл EXE или библиотеку DLL. Сведения об отладке необходимы для оптимального форматирования стеков вызовов. В следующем примере cl /fsanitize=address /Zi передается в командной строке.

Библиотеки 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

Снимок экрана: командная строка с командой для компиляции с параметрами AddressSanitizer. Команда : cl main.cpp -faanitize-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

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

  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]

Примечание.

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

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

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

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

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

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

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

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

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

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

    Снимок экрана: раскрывающийся список конфигурации CMake. В нем отображаются такие параметры, как отладка x64, выпуск x64 и т. д. В нижней части списка управление конфигурациями... выделен.

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

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

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

    "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. Средство очистки адресов не работает, если указан/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 в интегрированной среде разработки. Ошибка накладывается на источник, так же как и в динамическом сеансе отладки.

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

Чтобы создать новый тип файла дампа, который можно просмотреть в 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 — этот параметр включен по умолчанию и не может быть отключен.
  • стек-use-after-return — эта функция требует дополнительного параметра компилятора и не доступна только параметром ASAN_OPTIONS.

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

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

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

Существующая индустрия документация

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

В этом частичном документе по адресу AddressSanitizer (external) описывается реализация.

См. также

Известные проблемы AddressSanitizer
Справочник по сборке и языку AddressSanitizer
Справочник по среде выполнения AddressSanitizer
Теневой байт AddressSanitizer
Облачное или распределенное тестирование AddressSanitizer
Интеграция отладчика AddressSanitizer
Примеры ошибок AddressSanitizer