AddressSanitizer 언어, 빌드 및 디버깅 참조

이 문서의 섹션에서는 AddressSanitizer 언어 사양, 컴파일러 옵션 및 링커 옵션에 대해 설명합니다. 또한 AddressSanitizer와 관련된 Visual Studio 디버거 통합을 제어하는 옵션도 설명합니다.

AddressSanitizer 런타임에 대한 자세한 내용은 런타임 참조를 참조하세요. 여기에는 가로채는 함수 및 사용자 지정 할당자를 후크하는 방법에 대한 정보가 포함됩니다. AddressSanitizer 오류에서 크래시 덤프를 저장하는 방법에 대한 자세한 내용은 크래시 덤프 참조참조하세요.

언어 사양

__SANITIZE_ADDRESS__

__SANITIZE_ADDRESS__ 전처리기 매크로는 설정된 경우 /fsanitize=address1 정의됩니다. 이 매크로는 고급 사용자가 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
}

컴파일러

/fsanitize=address 컴파일러 옵션

/fsanitize=address 컴파일러 옵션은 코드에서 메모리 참조를 계측하여 런타임에 메모리 안전 오류를 catch합니다. 계측 후크는 로드, 저장소, 범위 alloca및 CRT 함수를 연결합니다. 범위를 벗어난 버그, 사용 후 사용, 사용 후 범위 등과 같은 숨겨진 버그를 검색할 수 있습니다. 런타임에 검색된 비동기 오류 목록은 AddressSanitizer 오류 예제를 참조 하세요.

/fsanitize=address는 모든 기존 C++ 또는 C 최적화 수준(예: /Od, , /O1/O2, /O2 /GL및 프로필 기반 최적화)과 호환됩니다. 이 옵션으로 생성된 코드는 정적 및 동적 CRT(예: /MD, /MDd, /MT/MTd)에서 작동합니다. 이 컴파일러 옵션을 사용하여 x86 또는 x64를 대상으로 하는 .EXE 또는 .DLL 만들 수 있습니다. 호출 스택의 최적의 서식을 지정하려면 디버그 정보가 필요합니다.

여러 종류의 오류 검색을 보여 주는 코드의 예제는 AddressSanitizer 오류 예제를 참조 하세요.

/fsanitize=fuzzer 컴파일러 옵션(실험적)

/fsanitize=fuzzer 컴파일러 옵션은 LibFuzzer를 기본 라이브러리 목록에 추가합니다. 또한 다음과 같은 소독제 검사 옵션을 설정합니다.

와 함께 /fsanitize=fuzzer사용하는 /fsanitize=address 것이 좋습니다.

다음을 지정 /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}

함수를 생략 main 하는 LibFuzzer 라이브러리도 사용할 수 있습니다. 이러한 라이브러리를 정의 main 하고 호출 LLVMFuzzerInitialize 하는 것은 사용자의 책임입니다 LLVMFuzzerTestOneInput . 이러한 라이브러리 중 하나를 사용하려면 런타임 및 아키텍처에 해당하는 다음 라이브러리를 지정 /NODEFAULTLIB 하고 명시적으로 연결합니다.

런타임 옵션 LibFuzzer no_기본 라이브러리
/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와 달리)는 반환 후 사용 오류를 catch하기 위해 힙의 프레임을 할당하는 코드를 생성하지 않습니다. AddressSanitizer를 사용하여 이러한 오류를 catch하려면 다음을 수행해야 합니다.

  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 규칙은 일반적으로 x86x64 및 대신.x86_64i386 동일한 아키텍처를 참조합니다.

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 옵션은 AddressSanitizer 예외가 throw될 때 향상된 Visual Studio 디버깅 환경을 위해 추가 라이브러리에 연결됩니다. 이러한 라이브러리를 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 IDE를 시작하도록 환경 변수를 설정할 수 있습니다. 이 컴파일러 옵션을 사용하면 오류를 발생시킨 정확한 줄과 열에서 소스 코드 위에 중첩된 오류를 볼 수 있습니다.

이 동작을 사용하도록 설정하려면 애플리케이션을 실행하기 전에 명령을 set ASAN_VCASAN_DEBUGGING=1 실행합니다. 를 실행 set ASAN_VCASAN_DEBUGGING=0하여 향상된 디버깅 환경을 사용하지 않도록 설정할 수 있습니다.

참고 항목

AddressSanitizer 개요
AddressSanitizer 알려진 문제
AddressSanitizer 런타임 참조
AddressSanitizer 섀도 바이트
AddressSanitizer 클라우드 또는 분산 테스트
AddressSanitizer 디버거 통합
AddressSanitizer 오류 예제