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


Справочник по языку, сборке и отладке AddressSanitizer

В разделах этой статьи описываются спецификация языка AddressSanitizer, параметры компилятора и параметры компоновщика. Они также описывают параметры, управляющие интеграцией отладчика Visual Studio, относящуюся к AddressSanitizer.

Дополнительные сведения о среде выполнения AddressSanitizer см. в справочнике по среде выполнения. В ней содержатся сведения о перехватанных функциях и способах перехвата пользовательских распределителей. Дополнительные сведения о сохранении аварийных дампов из сбоев AddressSanitizer см. в справочнике по аварийному дампе.

Спецификация языка

__SANITIZE_ADDRESS__

Макрос __SANITIZE_ADDRESS__ препроцессора определяется как 1 при /fsanitize=address установке. Этот макрос полезен для расширенных пользователей, чтобы условно указать исходный код для присутствия среды выполнения AddressSanitizer.

#include <cstdio>

int main() {
    #ifdef __SANITIZE_ADDRESS__
        printf("Address sanitizer enabled");
    #else
        printf("Address sanitizer not enabled");
    #endif
    return 1;
}

__declspec(no_sanitize_address)

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

__declspec(no_sanitize_address)
void test1() {
    int x[100];
    x[100] = 5; // ASan exception not caught
}

void test2() {
    __declspec(no_sanitize_address) int x[100];
    x[100] = 5; // ASan exception not caught
}

__declspec(no_sanitize_address) int g[100];
void test3() {
    g[100] = 5; // ASan exception not caught
}

GNU C ++

Параметр компилятора /fsanitize=address

Параметр /fsanitize=address компилятора инструментирует ссылки на память в коде для перехвата ошибок безопасности памяти во время выполнения. Перехватчик инструментирования загружает, хранит, области allocaи функции CRT. Он может обнаруживать скрытые ошибки, такие как вне границы, использование после использования, использование после области и т. д. Список ошибок, обнаруженных во время выполнения, см . в примерах ошибок AddressSanitizer.

/fsanitize=addressсовместим со всеми существующими уровнями оптимизации C++ или C (например, , /Od, /O2/O1и /O2 /GL). Код, созданный с помощью этого параметра, работает со статическими и динамическими crT (например, , /MD, /MDd/MTи /MTd). Этот параметр компилятора можно использовать для создания .EXE или .DLL, предназначенных для x86 или x64. Сведения об отладке необходимы для оптимального форматирования стеков вызовов. Этот параметр компилятора не поддерживается при оптимизации профиля.

Примеры кода, демонстрирующего несколько типов обнаружения ошибок, см . в примерах ошибок AddressSanitizer.

/fsanitize=fuzzer Параметр компилятора (экспериментальный)

Параметр /fsanitize=fuzzer компилятора добавляет LibFuzzer в список библиотек по умолчанию. Он также задает следующие параметры покрытия санитизатора:

Рекомендуется использовать /fsanitize=address /fsanitize=fuzzerс .

Эти библиотеки добавляются в список библиотек по умолчанию при указании /fsanitize=fuzzer:

Параметр среды выполнения Библиотека LibFuzzer
/MT clang_rt.fuzzer_MT-{arch}
/MD clang_rt.fuzzer_MD-{arch}
/MTd clang_rt.fuzzer_MTd-{arch}
/MDd clang_rt.fuzzer_MDd-{arch}

Также доступны библиотеки LibFuzzer, которые опустят функцию main . Вы несете ответственность за определение main и вызов LLVMFuzzerInitialize LLVMFuzzerTestOneInput и использование этих библиотек. Чтобы использовать одну из этих библиотек, укажите /NODEFAULTLIB и явным образом свяжите со следующей библиотекой, соответствующей среде выполнения и архитектуре:

Параметр среды выполнения Библиотека no_main LibFuzzer
/MT clang_rt.fuzzer_no_main_MT-{arch}
/MD clang_rt.fuzzer_no_main_MD-{arch}
/MTd clang_rt.fuzzer_no_main_MTd-{arch}
/MDd clang_rt.fuzzer_no_main_MDd-{arch}

Если вы укажете и не укажете /NODEFAULTLIB одну из этих библиотек, вы получите неразрешенную ошибку ссылки на внешние символы.

/fsanitize-address-use-after-return Параметр компилятора (экспериментальный)

По умолчанию компилятор MSVC (в отличие от Clang) не создает код для выделения кадров в куче для перехвата ошибок возврата после использования. Чтобы поймать эти ошибки с помощью AddressSanitizer, необходимо:

  1. Компиляция с помощью /fsanitize-address-use-after-return параметра.
  2. Перед выполнением программы запустите set ASAN_OPTIONS=detect_stack_use_after_return=1 , чтобы задать параметр проверки среды выполнения.

Этот /fsanitize-address-use-after-return параметр приводит к тому, что компилятор создает код для использования двух кадров стека в куче, когда локальные жители считаются "адресными". Этот код гораздо медленнее , чем просто использование /fsanitize=address в одиночку. Дополнительные сведения и пример см. в статье Об ошибке: stack-use-after-return

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

Кадры стека выделяются в куче и остаются после возврата функций. Среда выполнения использует сборку мусора для асинхронного освобождения этих поддельных объектов вызовов после определенного интервала времени. Адреса местных жителей передаются в постоянные кадры в куче. Это то, как система может определить, когда все локальные жители будут использоваться после возврата определяющей функции. Дополнительные сведения см. в алгоритме использования стека после возврата , как описано Google.

Компоновщик

/INFERASANLIBS[:NO] Параметр компоновщика

Параметр /fsanitize=address компилятора помечает объекты, чтобы указать библиотеку AddressSanitizer для связывания с исполняемым файлом. Библиотеки имеют имена, начинающиеся с clang_rt.asan*. Параметр /INFERASANLIBS компоновщика (по умолчанию) связывает эти библиотеки из их расположений по умолчанию автоматически. Ниже перечислены библиотеки, выбранные и автоматически связанные.

Примечание.

В следующей таблице имеет {arch} значение i386 или x86_64. Эти библиотеки используют соглашения Clang для имен архитектуры. Соглашения MSVC обычно x86 и x64 не i386 являются.x86_64 Они ссылаются на те же архитектуры.

Параметр CRT Библиотека среды выполнения AddressSanitizer (.lib) Двоичный файл среды выполнения адресов (.dll)
/MT или /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD или /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

Параметр /INFERASANLIBS:NO компоновщика запрещает компоновщику связывать clang_rt.asan* файл библиотеки из расположения по умолчанию. При использовании этого параметра добавьте путь к библиотеке в скрипты сборки. В противном случае компоновщик сообщает о неразрешенной ошибке внешнего символа.

Предыдущие версии

До Visual Studio 17.7(предварительная версия 3) статически связанные сборки (/MT или /MTd) не использовали зависимость DLL. Вместо этого среда выполнения AddressSanitizer была статически связана с EXE пользователя. Затем проекты DLL загружают экспорт из EXE пользователя для доступа к функциям ASan. Кроме того, динамически связанные проекты (/MD или /MTd) использовали разные библиотеки и библиотеки DLL в зависимости от того, настроен ли проект для отладки или выпуска. Дополнительные сведения об этих изменениях и их мотивациях см. в msVC Address Sanitizer — одна библиотека DLL для всех конфигураций среды выполнения.

Параметр среды выполнения CRT DLL или EXE Библиотеки среды выполнения AddressSanitizer
/MT EXE clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch}
/MT DLL-библиотеки clang_rt.asan_dll_thunk-{arch}
/MD Можно использовать clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch}
/MTd EXE clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch}
/MTd DLL-библиотеки clang_rt.asan_dbg_dll_thunk-{arch}
/MDd Можно использовать clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch}

Интеграция Visual Studio

Параметр компилятора /fno-sanitize-address-vcasan-lib

Ссылки /fsanitize=address на дополнительные библиотеки для улучшенной отладки Visual Studio при возникновении исключения AddressSanitizer. Эти библиотеки называются VCAsan. Библиотеки позволяют Visual Studio отображать ошибки AddressSanitizer в исходном коде. Они также позволяют исполняемому файлу создавать аварийные дампы при создании отчета об ошибке AddressSanitizer. Дополнительные сведения см. в библиотеке расширенных функциональных возможностей Visual Studio AddressSanitizer.

Выбранная библиотека зависит от параметров компилятора и автоматически связана.

Параметр среды выполнения Версия VCAsan
/MT libvcasan.lib
/MD vcasan.lib
/MTd libvcasand.lib
/MDd vcasand.lib

Однако при компиляции с помощью /Zl (опущено имя библиотеки по умолчанию), необходимо вручную указать библиотеку. Если вы этого не сделали, вы получите неразрешенную ошибку ссылки на внешние символы. Вот несколько типичных примеров:

error LNK2001: unresolved external symbol __you_must_link_with_VCAsan_lib
error LNK2001: unresolved external symbol ___you_must_link_with_VCAsan_lib

Улучшенная отладка может быть отключена во время компиляции с помощью /fno-sanitize-address-vcasan-lib параметра.

Переменная среды ASAN_VCASAN_DEBUGGING.

Параметр /fsanitize=address компилятора создает двоичный файл, предоставляющий ошибки безопасности памяти во время выполнения. При запуске двоичного файла из командной строки среда выполнения сообщает об ошибке, она выводит сведения об ошибке. Затем он завершает процесс. Переменная ASAN_VCASAN_DEBUGGING среды может быть задана, чтобы запустить интегрированную среду разработки Visual Studio сразу, когда среда выполнения сообщает об ошибке. Этот параметр компилятора позволяет просмотреть ошибку, наложенную на исходный код, в точной строке и столбце, вызвавшей ошибку.

Чтобы включить это поведение, выполните команду set ASAN_VCASAN_DEBUGGING=1 перед запуском приложения. Вы можете отключить расширенный интерфейс отладки, выполнив команду set ASAN_VCASAN_DEBUGGING=0.

См. также

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