Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описаны спецификация языка MSVC AddressSanitizer, параметры компилятора, параметры компоновщика и параметры, управляющие интеграцией отладчика Visual Studio, относящиеся к MSVC AddressSanitizer.
Дополнительные сведения о среде выполнения MSVC AddressSanitizer см. в справочнике по среде выполнения. В ней содержатся сведения о перехваченных функциях и о том, как подключить пользовательские распределители. Дополнительные сведения о сохранении дампов сбоев по причине неисправностей MSVC AddressSanitizer см. в справочной информации по аварийному дампу.
Спецификация языка
__SANITIZE_ADDRESS__
Макрос препроцессора __SANITIZE_ADDRESS__ определяется как 1, когда параметр /fsanitize=address установлен. Этот макрос полезен для условного указания исходного кода при наличии среды выполнения MSVC AddressSanitizer.
#include <cstdio>
int main()
{
#ifdef __SANITIZE_ADDRESS__
printf("MSVC AddressSanitizer enabled");
#else
printf("MSVC AddressSanitizer not enabled");
#endif
return 1;
}
__declspec(no_sanitize_address)
Описатель __declspec(no_sanitize_address) можно использовать для выборочного отключения санитизатора функций, локальных переменных или глобальных переменных. Это __declspec влияет на поведение компилятора , а не на поведение среды выполнения .
#ifdef __SANITIZE_ADDRESS__
// no_sanitize_address is only defined when compiling with MSVC AddressSanitizer.
// Guard against this by checking if `__SANITIZE_ADDRESS__` is defined.
#define NO_SANITIZE_ADDRESS __declspec(no_sanitize_address)
#else
#define NO_SANITIZE_ADDRESS
#endif
NO_SANITIZE_ADDRESS
void test1()
{
int x[100];
x[100] = 5; // ASan exception not caught
}
void test2()
{
NO_SANITIZE_ADDRESS int x[100];
x[100] = 5; // ASan exception not caught
}
NO_SANITIZE_ADDRESS int g[100];
void test3()
{
g[100] = 5; // ASan exception not caught
}
Компилятор
Параметр компилятора /fsanitize=address
Параметр /fsanitize=address компилятора добавляет инструментирование обращений к памяти в вашем коде для обнаружения ошибок безопасности памяти во время выполнения. Перехватчик инструментирования загружает, хранит, области, alloca и функции CRT. Он может обнаруживать скрытые ошибки, такие как выход за пределы, использование после освобождения, использование после выхода из области видимости и т. д. Список ошибок, обнаруженных во время выполнения, см. в примерах ошибок MSVC AddressSanitizer.
/fsanitize=addressсовместим со всеми существующими уровнями оптимизации C++ или C (например, , /Od, /O1/O2и /O2 /GL). Код, созданный с помощью этого параметра, работает со статическими и динамическими CRT (например, /MD, /MDd, /MT, и /MTd). Этот параметр компилятора можно использовать для создания .EXE или .DLL, предназначенных для x86 или x64. Сведения об отладке необходимы для оптимального форматирования стеков вызовов. Этот параметр компилятора не поддерживается при оптимизации профиля.
Примеры кода, демонстрирующего несколько видов обнаружения ошибок, см. в примерах ошибок MSVC AddressSanitizer.
/fsanitize=fuzzer Параметр компилятора (экспериментальный)
Параметр /fsanitize=fuzzer компилятора добавляет LibFuzzer в список библиотек по умолчанию. Он также устанавливает следующие параметры охвата санитизатора:
-
Точки инструментирования на краю (
/fsanitize-coverage=edge), -
встроенные 8-разрядные счетчики (
/fsanitize-coverage=inline-8bit-counters), -
сравнения (
/fsanitize-coverage=trace-cmp)и -
целочисленные деления (
/fsanitize-coverage=trace-div).
Рекомендуется использовать /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 и явным образом свяжите со следующей библиотекой, соответствующей среде выполнения и архитектуре:
| Параметр среды выполнения | Библиотека LibFuzzer no_main |
|---|---|
/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) не генерирует код для выделения памяти для кадров в куче с целью обнаружения ошибок типа use-after-return. Чтобы поймать эти ошибки с помощью MSVC AddressSanitizer, необходимо:
- Компиляция с помощью
/fsanitize-address-use-after-returnпараметра. - Перед выполнением программы запустите
set ASAN_OPTIONS=detect_stack_use_after_return=1, чтобы задать параметр проверки среды выполнения.
Этот /fsanitize-address-use-after-return параметр заставляет компилятор создавать код для использования двойной стековой рамки в куче, когда локальные переменные рассматриваются как нуждающиеся в адресации. Этот код гораздо медленнее, чем просто использование /fsanitize=address отдельно. Дополнительные сведения и пример см. в статье Об ошибке: stack-use-after-return
Кадр двух стеков в куче остается после возврата из функции, которая его создала. Рассмотрим пример, когда адрес локальной переменной, выделенной в слоте в куче, используется после возврата. Теневые байты, связанные с фиктивным кадром кучи, содержат значение 0xF9. Это 0xF9 указывает на ошибку использования стека после возврата, когда среда выполнения сообщает об ошибке.
Кадры стека выделяются в куче и остаются после возврата функций. Среда выполнения использует сборку мусора для асинхронного освобождения этих фальшивых кадров вызова после определенного интервала времени. Адреса локальных переменных передаются в постоянные фреймы в куче. Это то, как система может определить, когда локальные переменные используются после возврата определяющей функции. Дополнительные сведения см. в алгоритме использования стека после возврата, в документации от Google.
Встроенная библиотека совместимости ASan
При создании с помощью ASan компилятор заменяет встроенные функции (например, memset) вызовами функций, предоставляемых библиотекой среды выполнения ASan (например, __asan_memset), которые выполняют ту же операцию, но также обеспечивают проверки безопасности памяти. Для ASan в пользовательском режиме компилятор и среда выполнения обновляются вместе, так как Visual Studio предоставляет оба варианта.
Режим ядра ASan (KASan) является частью ОС Windows, поэтому он обновляется по-другому по сравнению с компилятором. Чтобы избежать проблем с новым компилятором с помощью новых встроенных компонентов, которые установленная версия KASan не поддерживает, свяжите библиотеку совместимости (asan_compat.lib), чтобы избежать проблем со временем связи. При использовании asan_compat.libпрограмма ведет себя так, как будто неподдерживаемые встроенные компоненты ASan не используются. Связывание с новой библиотекой среды выполнения, которая поддерживает новые встроенные функции ASan, заменяет версии, предоставляемые asan_compat.lib. Это решение принимается во время ссылки, поэтому необходимо связаться с библиотекой KASan, предоставленной пакетом SDK для Windows, который соответствует целевой версии ОС.
В Visual Studio 2022 17.14 preview 2 и более поздних версиях поддерживаются следующие параметры:
- Чтобы включить эту библиотеку совместимости в качестве библиотеки по умолчанию, используйте параметр компилятора
/fsanitize-address-asan-compat-lib. Этот параметр автоматически включен при использовании/fsanitize=kernel-address. - Чтобы отказаться от этой библиотеки совместимости, используйте параметр компилятора
/fno-sanitize-address-asan-compat-lib.
Использование /fsanitize-address-asan-compat-lib для связывания нового компилятора с более старой средой выполнения ASan в пользовательском режиме в настоящее время не поддерживается.
Компоновщик
/INFERASANLIBS[:NO] Параметр компоновщика
Параметр /fsanitize=address компилятора помечает объекты, чтобы указать библиотеку MSVC AddressSanitizer для связывания с исполняемым файлом. Библиотеки имеют имена, начинающиеся с clang_rt.asan*. Параметр /INFERASANLIBS компоновщика по умолчанию автоматически связывает эти библиотеки из их стандартных местоположений. Ниже перечислены библиотеки, выбранные и автоматически связанные.
Примечание.
В следующей таблице {arch} либо i386, либо x86_64.
Эти библиотеки используют соглашения Clang для имен архитектуры. Соглашения MSVC обычно x86 и x64, а не i386 и x86_64. Они ссылаются на те же архитектуры.
| Параметр CRT | Библиотека среды выполнения MSVC AddressSanitizer (.lib) | Двоичный файл среды выполнения адресов (.dll) |
|---|---|---|
/MT или /MTd |
clang_rt.asan_dynamic-{arch}.lib, /wholearchive:clang_rt.asan_static_runtime_thunk-{arch}.lib |
clang_rt.asan_dynamic-{arch}.dll |
/MD или /MDd |
clang_rt.asan_dynamic-{arch}.lib, /wholearchive:clang_rt.asan_dynamic_runtime_thunk-{arch}.lib |
clang_rt.asan_dynamic-{arch}.dll |
Параметр /INFERASANLIBS:NO компоновщика запрещает компоновщику связывать clang_rt.asan* файл библиотеки из расположения по умолчанию. При использовании этого параметра добавьте путь к библиотеке в скрипты сборки. В противном случае компоновщик сообщает об ошибке связанной с неразрешённым внешним символом. Библиотеки промежуточного уровня среды выполнения должны быть связаны с использованием параметра /wholearchive.
Предыдущие версии
До Visual Studio 17.7(предварительная версия 3) статически связанные сборки (/MT или /MTd) не использовали зависимость DLL. Вместо этого среда выполнения MSVC AddressSanitizer была статически связана с EXE пользователя. Затем проекты DLL загружают экспорт из EXE пользователя для доступа к функциям ASan. Кроме того, динамически связанные проекты (/MD или /MTd) использовали разные библиотеки и библиотеки DLL в зависимости от того, настроен ли проект для отладки или выпуска. Дополнительные сведения об этих изменениях и их мотивации см. в статье MSVC AddressSanitizer — одна библиотека DLL для всех конфигураций среды выполнения.
| Параметр среды выполнения CRT | DLL или EXE | Библиотеки среды выполнения MSVC AddressSanitizer |
|---|---|---|
/MT |
EXE |
/wholearchive:clang_rt.asan-{arch}.lib, clang_rt.asan_cxx-{arch}.lib |
/MT |
DLL | /wholearchive:clang_rt.asan_dll_thunk-{arch}.lib |
/MD |
Либо |
clang_rt.asan_dynamic-{arch}.lib, /wholearchive:clang_rt.asan_dynamic_runtime_thunk-{arch}.lib |
/MTd |
EXE |
/wholearchive:clang_rt.asan_dbg-{arch}.lib, clang_rt.asan_cxx_dbg-{arch}.lib |
/MTd |
DLL | /wholearchive:clang_rt.asan_dbg_dll_thunk-{arch}.lib |
/MDd |
Либо |
/wholearchive:clang_rt.asan_dbg_dynamic-{arch}.lib, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch}.lib |
Интеграция Visual Studio
Параметр компилятора /fno-sanitize-address-vcasan-lib
Опция /fsanitize=address подключает дополнительные библиотеки для улучшения процесса отладки в Visual Studio при возникновении исключения MSVC AddressSanitizer. Эти библиотеки называются VCAsan. Библиотеки позволяют Visual Studio отображать ошибки MSVC AddressSanitizer в исходном коде. Они также позволяют исполняемому файлу создавать аварийные дампы при создании отчета об ошибке MSVC AddressSanitizer. Дополнительные сведения см. в библиотеке расширенных функциональных возможностей Visual Studio MSVC 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.
См. также
Обзор MSVC AddressSanitizer
Известные проблемы MSVC AddressSanitizer
Справочник по времени выполнения MSVC AddressSanitizer
MSVC AddressSanitizer теневые байты
Облачное или распределенное тестирование MSVC AddressSanitizer
Интеграция отладчика MSVC AddressSanitizer
Примеры ошибок MSVC AddressSanitizer