다음을 통해 공유


AddressSanitizer

개요

C & C++ 언어는 강력하지만 프로그램 정확성 및 프로그램 보안에 영향을 주는 버그 클래스로 인해 어려움을 겪을 수 있습니다. Visual Studio 2019 버전 16.9부터 Microsoft C/C++ 컴파일러(MSVC) 및 IDE는 AddressSanitizer 소독기를 지원합니다. AddressSanitizer(ASan)는 가양성이 없는 찾기 어려운 많은 버그를 노출하는 컴파일러 및 런타임 기술입니다.

AddressSanitizer를 사용하여 소요된 시간을 줄입니다.

  • 기본 정확성
  • 플랫폼 간 이식성
  • 보안
  • 스트레스 테스트
  • 새 코드 통합

원래 Google에서 도입한 AddressSanitizer는 기존 빌드 시스템과 기존 테스트 자산을 직접 사용하는 런타임 버그 찾기 기술을 제공합니다.

AddressSanitizer는 Visual Studio 프로젝트 시스템, CMake 빌드 시스템 및 IDE와 통합됩니다. 프로젝트는 프로젝트 속성을 설정하거나 하나의 추가 컴파일러 옵션을 /fsanitize=address사용하여 AddressSanitizer를 사용하도록 설정할 수 있습니다. 새 옵션은 x86 및 x64의 모든 수준의 최적화 및 구성과 호환됩니다. 그러나 편집 및 계속, 증분 연결/RTC.

Visual Studio 2019 버전 16.9부터 Microsoft의 AddressSanitizer 기술을 통해 Visual Studio IDE와 통합할 수 있습니다. 이 기능은 소독기가 런타임에 버그를 발견할 때 필요에 따라 크래시 덤프 파일을 만들 수 있습니다. 프로그램을 실행하기 전에 환경 변수를 ASAN_SAVE_DUMPS=MyFileName.dmp 설정하면 정확하게 진단된 버그의 효율적인 사후 분석 디버깅을 위해 추가 메타데이터가 포함된 크래시 덤프 파일이 만들어집니다. 이러한 덤프 파일은 다음을 위해 AddressSanitizer를 더 쉽게 사용할 수 있도록 합니다.

  • 로컬 컴퓨터 테스트
  • 온-프레미스 분산 테스트
  • 테스트를 위한 클라우드 기반 워크플로

AddressSanitizer 설치

Visual Studio 설치 관리자 C++ 워크로드는 기본적으로 AddressSanitizer 라이브러리 및 IDE 통합을 설치합니다. 그러나 이전 버전의 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 통합

다시 컴파일한 다음, 프로그램을 정상적으로 실행합니다. 이 코드 생성은 정확하게 진단된 여러 유형의 버그를 노출합니다. 이러한 오류는 디버거 IDE, 명령줄 또는 정확한 오프라인 처리를 위해 새 유형의 덤프 파일에 저장되는 세 가지 방법으로 보고됩니다.

다음 세 가지 표준 워크플로에서 AddressSanitizer를 사용하는 것이 좋습니다.

이 문서에서는 이전에 나열된 세 가지 워크플로를 사용하도록 설정하는 데 필요한 정보를 설명합니다. 이 정보는 AddressSanitizer의 플랫폼 종속 Windows 10 이상 구현과 관련이 있습니다. 이 설명서는 이미 게시된 Google, Apple 및 GCC우수한 설명서를 보완합니다.

참고 항목

지원은 Windows 10 이상에서 x86 및 x64로 제한됩니다. 향후 릴리스에서 보고 싶은 내용에 대한 피드백을 보내주세요. 피드백은 향후 다른 소독제(예: /fsanitize=thread, /fsanitize=leak, /fsanitize=undefined/fsanitize=memory또는 /fsanitize=hwaddress.)의 우선 순위를 지정하는 데 도움이 됩니다. 문제가 발생하면 여기에서 버그를 보고할 수 있습니다.

개발자 명령 프롬프트에서 AddressSanitizer 사용

/fsanitize=address 개발자 명령 프롬프트에서 컴파일러 옵션을 사용하여 AddressSanitizer 런타임에 대한 컴파일을 사용하도록 설정합니다. 이 /fsanitize=address 옵션은 모든 기존 C++ 또는 C 최적화 수준(예: /Od,, /O2 /GL/O1/O2및)과 PGO호환됩니다. 이 옵션은 정적 및 동적 CRT(예: /MD, , /MDd/MT및)에서 /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 실행하면 다음에 형식이 지정된 오류 보고서가 만들어집니다.

7가지 주요 정보를 강조 표시하는 오버레이된 빨간색 상자를 고려합니다.

기본 전역 오버플로 오류를 보여 주는 디버거의 스크린샷.

오류 보고서에는 주요 정보를 식별하는 7개의 빨간색 강조 표시가 있습니다. 이 스크린샷 뒤에 오는 번호 매기기 목록에 매핑됩니다. 번호가 매겨진 상자에는 다음 텍스트가 강조 표시됩니다. 1) global-buffer-overflow 2) WRITE of size 4 3) basic-global-overflow.cpp 7 4) 'basic-global-overflow.cpp :3:8' 5) 크기 400 6) 00 00[f9]f9 f9 7) 상자는 그림자 바이트 범례 영역에 있으며 글로벌 redzone을 포함: f9

위에서 아래로 빨간색 강조 표시

  1. 메모리 안전 버그는 전역 버퍼 오버플로입니다.
  2. 사용자 정의 변수 외부에 4바이트(32비트)가 저장되었습니다.
  3. 저장소는 7줄의 파일에 basic-global-overflow.cpp 정의된 함수 main() 에서 일어났습니다.
  4. 명명된 x 변수는 8열에서 시작하여 줄 3의 basic-global-overflow.cpp 정의됩니다.
  5. 이 전역 변수 x 의 크기는 400바이트입니다.
  6. 저장소가 대상으로 하는 주소를 설명하는 정확한 섀도 바이트 값은 입니다. 0xf9
  7. 그림자 바이트 범례는 오른쪽의 안쪽 여백 영역이라고 합니다 0xf9 . int x[100]

참고 항목

호출 스택의 함수 이름은 오류 발생 시 런타임에 의해 호출되는 LLVM 기호 변환기를 통해 생성됩니다.

Visual Studio에서 AddressSanitizer 사용

AddressSanitizer는 Visual Studio IDE와 통합됩니다. MSBuild 프로젝트에 대해 AddressSanitizer를 켜려면 솔루션 탐색기 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 속성 페이지 대화 상자에서 구성 속성>C/C++>일반을 선택한 다음 AddressSanitizer 사용 속성을 수정합니다. 확인을 선택하여 변경 내용을 저장합니다.

AddressSanitizer 사용 속성을 보여 주는 속성 페이지 대화 상자의 스크린샷

IDE에서 빌드하려면 호환되지 않는 옵션을 옵트아웃 합니다. (또는 디버그 모드)를 사용하여 /Od 컴파일된 기존 프로젝트의 경우 다음 옵션을 해제해야 할 수 있습니다.

디버거를 빌드하고 실행하려면 F5 키를 누릅니다. 예외 throw 창이 Visual Studio에 표시됩니다.

전역 버퍼 오버플로 오류를 보여 주는 디버거의 스크린샷

Visual Studio에서 AddressSanitizer 사용: CMake

Windows를 대상으로 만들기 위해 만든 CMake 프로젝트에 AddressSanitizer를 사용하도록 설정하려면 다음 단계를 수행합니다.

  1. IDE 위쪽의 도구 모음에서 구성 드롭다운을 열고 구성 관리를 선택합니다.

    CMake 구성 드롭다운의 스크린샷. x64 디버그, x64 릴리스 등의 옵션이 표시됩니다. 목록 맨 아래에 구성 관리... 가 강조 표시되어 있습니다.

    프로젝트 파일의 내용을 반영하는 CMake 프로젝트 CMakeSettings.json 설정 편집기가 열립니다.

  2. 편집기에서 JSON 편집 링크를 선택합니다. 이 선택 영역은 보기를 원시 JSON으로 전환합니다.

  3. 주소 삭제기를 켜려면 "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. 새 CMake 프로젝트에 대해 기본적으로 사용하도록 설정되는 edit-and-continue가/ZI 지정된 경우 주소 삭제기가 작동하지 않습니다. 에서 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. 이 JSON 파일을 저장하려면 Ctrl+S를 입력합니다.

  6. CMake 캐시 디렉터리를 지우고 Visual Studio 메뉴에서 >Project Delete 캐시 및 다시 구성을 선택하여 다시 구성합니다. 캐시 디렉터리를 지우고 다시 구성하라는 프롬프트가 나타나면 예를 선택합니다.

  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의 새로운 기능을 도입했습니다. 이 기능을 사용하면 IDE에서 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에서 가양성으로 이어질 수 있는 기능은 포함되지 않았습니다. 이 분야는 수십 년간의 기존 코드와의 상호 운용성을 고려할 때 필요한 효과적인 테스트 무결성을 적용했습니다. 이후 릴리스에서는 더 많은 기능을 고려할 수 있습니다.

자세한 내용은 MSVC를 사용하여 AddressSanitizer용 빌드를 참조하세요.

기존 업계 설명서

AddressSanitizer 기술의 이러한 언어 및 플랫폼 종속 구현에 대한 광범위한 설명서가 이미 있습니다.

AddressSanitizer(외부)이 정액 문서에서는 구현에 대해 설명합니다.

참고 항목

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