AddressSanitizer

Överblick

C- och C++-språken är kraftfulla, men kan drabbas av en klass buggar som påverkar programmets korrekthet och programsäkerhet. Från och med Visual Studio 2019 version 16.9 stöder kompilatorn Microsoft C/C++ (MSVC) och IDE AddressSanitizer sanitizer. AddressSanitizer (ASan) är en kompilator- och körningsteknologi som exponerar många svårsökta buggar med noll falska positiva identifieringar.

Varför använda AddressSanitizer

Använd AddressSanitizer för att minska din tid på:

  • Grundläggande korrekthet
  • Plattformsoberoende portabilitet
  • Säkerhet
  • Belastningstest
  • Integrera ny kod

AddressSanitizer, som ursprungligen introducerades av Google, tillhandahåller felsökningstekniker som körs och använder dina befintliga byggsystem och befintliga testresurser direkt.

Skapa integrering och kompatibilitet

AddressSanitizer är integrerat med Visual Studio-projektsystemet, CMake-byggsystemet och IDE. Projekt kan aktivera AddressSanitizer genom att ange en projektegenskap eller genom att använda ett extra kompilatoralternativ: /fsanitize=address. Det här alternativet är kompatibelt med alla nivåer av optimering och konfigurationer av x86 och x64. Det är dock inte kompatibelt med redigera och fortsätt, inkrementell länkningoch /RTC.

Stöd för kraschdumpar

Från och med Visual Studio 2019 version 16.9 möjliggör Microsofts AddressSanitizer-teknik integrering med Visual Studio IDE. Funktionen kan valfritt skapa en kraschdumpfil när sanitizern hittar en bugg vid körning. Om du ställer in ASAN_SAVE_DUMPS=MyFileName.dmp miljövariabeln innan du kör ditt program skapas en kraschdumpfil med extra metadata för effektiv post-mortem felsökning av exakt diagnostiserade fel. Dessa dumpfiler gör utökad användning av AddressSanitizer enklare för:

  • Testning av lokala datorer
  • Lokal distribuerad testning
  • Molnbaserade arbetsflöden för testning

Installera AddressSanitizer

C++-arbetsbelastningar i Visual Studio Installer installerar AddressSanitizer-biblioteken och IDE-integreringen som standard. Om du uppgraderar från en äldre version av Visual Studio 2019 använder du installationsprogrammet för att aktivera ASan-stöd efter uppgraderingen. Du kan öppna installationsprogrammet från huvudmenyn Visual Studio genom att välja Tools>Get Tools and Features. Välj Modify på din befintliga Visual Studio installation från Visual Studio Installer för att komma till följande skärm.

En skärmbild som visar Visual Studio Installer, där komponenten C++ AddressSanitizer är markerad under avsnittet Valfritt.

Not

Om du kör Visual Studio på den nya uppdateringen men inte har installerat ASan får du ett fel när du kör koden:

LNK1356: kan inte hitta biblioteket "clang_rt.asan_dynamic-i386.lib"

Använda AddressSanitizer

Börja skapa körbara filer med alternativet /fsanitize=address kompilator med någon av dessa vanliga utvecklingsmetoder:

  • Kompilering från kommandorad
  • Visual Studio-projektsystem
  • Visual Studio CMake-integrering

Kompilera om koden och kör sedan programmet normalt för att exponera många typer av exakt diagnostiserade buggar. Du kan granska problemen i felsökningsprogrammets IDE, kommandoraden eller dumpfilen.

Microsoft rekommenderar att du använder AddressSanitizer i dessa tre standardarbetsflöden:

Den här artikeln beskriver den information du behöver för att aktivera de tre arbetsflöden som angavs tidigare. Informationen är specifik för plattformsberoende Windows 10-implementering (och senare) av AddressSanitizer. Den här dokumentationen kompletterar dokumentationen från Google, Apple och GCC.

Not

Stödet är begränsat till x86 och x64 i Windows 10 och senare. Skicka oss feedback om vad du vill se i framtida versioner. Din feedback hjälper oss att prioritera andra sanitizers för framtiden, till exempel /fsanitize=thread, /fsanitize=leak, /fsanitize=memory, /fsanitize=undefinedeller /fsanitize=hwaddress. Du kan rapportera buggar här om du stöter på problem.

Använd AddressSanitizer från en utvecklarkommandotolk

Använd alternativet /fsanitize=address kompilator i en kommandotolk för utvecklare för att aktivera kompilering för AddressSanitizer-körningen. Alternativet /fsanitize=address är kompatibelt med befintliga C++ eller C-optimeringsnivåer, /Odtill exempel , , /O1/O2och /O2 /GL. Alternativet fungerar med statiska och dynamiska CRT(till exempel /MD, /MDd, /MToch /MTd). Det fungerar oavsett om du skapar en EXE eller en DLL. Felsökningsinformation krävs för optimal formatering av anropsstackar. I följande exempel skickas cl /fsanitize=address /Zi på kommandoraden.

Not

AddressSanitizer stöder inte profilstyrd optimering (PGO). AddressSanitizer ska inte användas i produktion.

AddressSanitizer-biblioteken (.lib-filer) länkas automatiskt åt dig. Mer information finns i AddressSanitizer språk-, kompilering- och felsökningsreferens.

Exempel – grundläggande global buffertöverskridning

// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
    printf("Hello!\n");
    x[100] = 5; // Boom!
    return 0;
}

Kompilera basic-global-overflow.cpp med hjälp av /fsanitize=address /Zi med hjälp av en kommandotolk för utvecklare för Visual Studio 2019.

Skärmbild som visar en kommandotolk med kommandot

När du kör den resulterande basic-global-overflow.exe på kommandoraden skapas den formaterade felrapporten som följer.

Tänk på de överlagrade, röda rutorna som markerar sju viktiga informationsdelar:

Skärmbild av felsökningsprogrammet som visar ett grundläggande globalt spillfel.

Röda markeringar, uppifrån och ned

  1. Minnessäkerhetsbuggen är en global buffertöverskridning.
  2. Det fanns 4 byte (32 bitar) lagrade utanför någon användardefinierad variabel.
  3. Lagringen ägde rum i funktionen main() definierad i filen basic-global-overflow.cpp på rad 7.
  4. Variabeln med namnet x definieras i basic-global-overflow.cpp på rad 3, med början i kolumn 8.
  5. Den här globala variabeln x är av storlek 400 byte.
  6. Det exakta skuggbyte som beskrev adressen som skrivningen riktades mot hade värdet 0xf9.
  7. Teckenförklaringen för skuggbyten anger att 0xf9 är ett utfyllnadsområde till höger om int x[100].

Not

När AddressSanitizer rapporterar ett fel anropar ASan-körningen LLVM-symboliseraren för att skapa funktionsnamnen i anropsstacken.

Använda AddressSanitizer i Visual Studio

AddressSanitizer är integrerat med Visual Studio IDE. Om du vill aktivera AddressSanitizer för ett MSBuild-projekt högerklickar du på projektet i Prieskumník riešení och väljer Egenskaper. I dialogrutan egenskapssidor väljer du Konfigurationsegenskaper>C/C++>Allmäntoch ändrar sedan egenskapen Aktivera AddressSanitizer. Välj OK för att spara ändringarna.

Skärmbild av dialogrutan Egenskapssidor som visar egenskapen Aktivera AddressSanitizer.

Om du vill skapa från IDE väljer du bort alla inkompatibla alternativ. För ett befintligt projekt som har kompilerats med hjälp av /Od (eller i felsökningsläge) kan du behöva stänga av följande alternativ:

Om du vill skapa och köra felsökningsprogrammet trycker du på F5. Ett kastat undantag visas i Visual Studio.

Skärmbild av felsökningsprogrammet som visar ett globalt buffertspillfel.

Använda AddressSanitizer från Visual Studio: CMake

Så här aktiverar du AddressSanitizer för ett CMake-projekt som skapats för att rikta in sig på Windows:

  1. Öppna listrutan Konfigurationer i verktygsfältet överst i IDE och välj Hantera konfigurationer.

    Skärmbild som visar listrutan CMake-konfiguration som visar alternativ som x64 Debug, x64 Release och, längst ned i listan, Hantera konfigurationer... är markerat.

    Den här åtgärden öppnar redigeraren CMake Project Settings, som återspeglar innehållet i filen project CMakeSettings.json.

  2. Välj länken Redigera JSON . Detta val växlar vyn till rå JSON.

  3. Om du vill aktivera AddressSanitizer lägger du till följande kodfragment i förinställningen "windows-base" i "configurePresets":.

    "environment": {
      "CFLAGS": "/fsanitize=address",
      "CXXFLAGS": "/fsanitize=address"
    }
    

    "configurePresets" ser ut ungefär så här efteråt:

        "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. AddressSanitizer fungerar inte om edit-and-continue har angetts (/ZI), vilket är aktiverat som standard för nya CMake-projekt. I CMakeLists.txtkommenterar du ut (prefix med #) raden som börjar med set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT". Den linjen ser ut ungefär så här:

    # 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. Använd Ctrl+S för att spara den här JSON-filen.

  6. Rensa CMake-cachekatalogen och konfigurera om genom att välja från Visual Studio-menyn: Project>Ta bort cache och Konfigurera om. Välj Ja när kommandotolken visas för att rensa cachekatalogen och konfigurera om.

  7. Ersätt innehållet i källfilen, till exempel CMakeProject1.cpp, med följande kod:

    // 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. Välj F5- för att kompilera om och köra under felsökningsprogrammet.

    Den här skärmbilden fångar upp felet från CMake-versionen.

    Skärmbild som visar ett undantag med texten: Address Sanitizer-fel: globalt buffertöverskridande.

AddressSanitizer kraschdumpar

AddressSanitizer innehåller funktioner för användning med molnbaserade och distribuerade arbetsflöden. Den här funktionen tillåter offlinevisning av ett AddressSanitizer-fel i IDE. Felet läggs över ovanpå källan, precis som du skulle uppleva i en live-felsökningssession.

Dessa dumpfiler kan leda till effektivitetsvinster när du analyserar en bugg. Du behöver inte köra igen, hitta fjärrdata eller leta efter en dator som gick offline.

Så här skapar du en dumpfil som du kan visa i Visual Studio på en annan dator vid ett senare tillfälle:

set ASAN_SAVE_DUMPS=MyFileName.dmp

Från och med Visual Studio 16.9 kan du visa en exakt diagnostiserat fel som lagras i filen *.dmp ovanpå källkoden.

Den här funktionen för kraschdumpar möjliggör molnbaserade arbetsflöden eller distribuerad testning. Den kan också användas för att skapa en detaljerad, åtgärdsbar bugg i alla scenarier.

Exempelfel

AddressSanitizer kan identifiera flera typer av fel vid minnesanvändning. Här är många av körningsfelen som rapporteras när du kör binärfilerna som kompilerats med hjälp av kompileringsalternativet AddressSanitizer (/fsanitize=address) :

Mer information om exemplen finns i AddressSanitizer-felexempel.

Skillnader med Clang 12.0

MSVC skiljer sig för närvarande från Clang 12.0 i två funktionella områden:

  • stack-use-after-scope: den här inställningen är aktiverad som standard och kan inte stängas av.
  • stack-use-after-return: Den här funktionen kräver ett extra kompilatoralternativ och är inte tillgängligt genom att bara ange ASAN_OPTIONS.

Dessa beslut fattades för att minska den testmatris som krävs för att leverera den första versionen.

Funktioner som kunde leda till falska positiva resultat i Visual Studio 2019 16.9 inkluderades inte. Den disciplinen framtvingade den effektiva testintegritet som krävdes när man övervägde interop med årtionden av befintlig kod. Fler funktioner kan övervägas i senare versioner:

Mer information finns i Building for AddressSanitizer with MSVC.

Branschdokumentation

Det finns omfattande dokumentation för dessa språk- och plattformsberoende implementeringar av AddressSanitizer-tekniken.

Det här viktiga dokumentet om AddressSanitizer (extern) beskriver implementeringen.

Se även