AddressSanitizer

Overzicht

De C- en C++-talen zijn krachtig, maar kunnen last hebben van een klasse bugs die van invloed zijn op de juistheid van het programma en de beveiliging van het programma. Vanaf Visual Studio 2019 versie 16.9 ondersteunen de Microsoft C/C++-compiler (MSVC) en IDE de AddressSanitizer opschoning. AddressSanitizer (ASan) is een compiler- en runtimetechnologie die veel moeilijk te vinden bugs blootstelt met nul fout-positieven:

Waarom AddressSanitizer gebruiken

Gebruik AddressSanitizer om uw tijd te verminderen die u hebt besteed aan:

  • Basis correctheid
  • Platformoverschrijdende draagbaarheid
  • Veiligheid
  • Stresstesten
  • Nieuwe code integreren

AddressSanitizer, oorspronkelijk geïntroduceerd door Google, biedt runtime bug-finding technologieën die uw bestaande buildsystemen en bestaande testassets rechtstreeks gebruiken.

Integratie en compatibiliteit bouwen

AddressSanitizer is geïntegreerd met het Visual Studio-projectsysteem, het CMake-buildsysteem en de IDE. Projecten kunnen AddressSanitizer inschakelen door een projecteigenschap in te stellen of door een extra compileroptie te gebruiken: /fsanitize=address. Deze optie is compatibel met alle niveaus van optimalisatie en configuraties van x86 en x64. Het is echter niet compatibel met bewerken en doorgaan, incrementele koppelingen /RTC.

Ondersteuning voor crashdumps

Vanaf Visual Studio 2019 versie 16.9 maakt de AddressSanitizer-technologie van Microsoft integratie mogelijk met de Visual Studio IDE. De functionaliteit kan eventueel een crashdumpbestand maken wanneer de opschoningsfunctie tijdens runtime een fout vindt. Als u de omgevingsvariabele ASAN_SAVE_DUMPS=MyFileName.dmp instelt voordat u uw programma uitvoert, wordt er een crashdumpbestand gemaakt met extra metagegevens voor efficiënte post-mortem-foutopsporing van nauwkeurig opgegeven fouten. Deze dumpbestanden maken uitgebreid gebruik van AddressSanitizer eenvoudiger voor:

  • Testen van lokale machines
  • Op locatie gedistribueerd testen
  • Cloudwerkstromen voor testen

AddressSanitizer installeren

C++-workloads in het Installatieprogramma van Visual Studio installeren standaard de AddressSanitizer-bibliotheken en IDE-integratie. Als u echter een upgrade uitvoert van een oudere versie van Visual Studio 2019, gebruikt u het installatieprogramma om ASan-ondersteuning in te schakelen na de upgrade. U kunt het installatieprogramma openen in het hoofdmenu van Visual Studio door Tools>Get Tools and Features te selecteren. Kies Modify op uw bestaande Visual Studio installatie vanuit het Visual Studio-installatieprogramma om naar het volgende scherm te gaan.

Schermafbeelding van het Visual Studio-installatieprogramma waarin het onderdeel C++ AddressSanitizer in de sectie Optioneel is gemarkeerd.

Notitie

Als u Visual Studio uitvoert op de nieuwe update, maar ASan nog niet hebt geïnstalleerd, krijgt u een foutmelding wanneer u de code uitvoert:

LNK1356: bibliotheek 'clang_rt.asan_dynamic-i386.lib' niet vinden

AddressSanitizer gebruiken

Begin met het bouwen van uw uitvoerbare bestanden met de /fsanitize=address compileroptie met behulp van een van deze algemene ontwikkelmethoden:

  • Opdrachtregelbuilds
  • Visual Studio-projectsysteem
  • Visual Studio CMake-integratie

Compileer uw code opnieuw en voer vervolgens uw programma normaal uit om veel soorten nauwkeurig opgegeven bugs bloot te stellen. U kunt de problemen in de foutopsporingsprogramma-IDE, de opdrachtregel of het dumpbestand bekijken.

Microsoft raadt u aan AddressSanitizer te gebruiken in deze drie standaardwerkstromen:

In dit artikel wordt beschreven welke informatie u nodig hebt om de drie eerder vermelde werkstromen in te schakelen. De informatie is specifiek voor de platformafhankelijke Windows 10 (en hoger) implementatie van AddressSanitizer. Deze documentatie is een aanvulling op de documentatie van Google, Apple en GCC.

Notitie

Ondersteuning is beperkt tot x86 en x64 in Windows 10 en hoger. Stuur ons feedback over wat u in toekomstige releases wilt zien. Uw feedback helpt ons prioriteit te geven aan andere sanitizers voor de toekomst, zoals /fsanitize=thread, /fsanitize=leak, /fsanitize=memory, /fsanitize=undefined, of /fsanitize=hwaddress. U kunt hier fouten melden als u problemen ondervindt.

AddressSanitizer gebruiken vanuit een opdrachtprompt voor ontwikkelaars

Gebruik de optie /fsanitize=address compiler in een opdrachtprompt voor ontwikkelaars om compiling in te schakelen voor de AddressSanitizer-runtime. De /fsanitize=address optie is compatibel met bestaande C++ of C-optimalisatieniveaus, bijvoorbeeld , /Od/O1, /O2en /O2 /GL. De optie werkt met statische en dynamische CRT's (bijvoorbeeld /MD, /MDd, /MTen /MTd). Het werkt of u een EXE of een DLL maakt. Foutopsporingsinformatie is vereist voor een optimale opmaak van aanroepstacks. In het volgende voorbeeld wordt cl /fsanitize=address /Zi doorgegeven op de opdrachtregel.

Notitie

AddressSanitizer biedt geen ondersteuning voor PGO (Profile-Guided Optimization). AddressSanitizer mag niet worden gebruikt in productie.

De AddressSanitizer-bibliotheken (.lib-bestanden) worden automatisch aan u gekoppeld. Zie AddressSanitizer-taal, build- en foutopsporingsreferentievoor meer informatie.

Voorbeeld: algemene bufferoverloop basis

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

Compileer met behulp van een opdrachtprompt voor ontwikkelaars voor Visual Studio 2019 basic-global-overflow.cpp met behulp van /fsanitize=address /Zi.

Schermopname van een opdrachtprompt met de opdracht 'cl basic-global-overflow.cpp /fsanitize=address /Zi'.

Wanneer u de resulterende basic-global-overflow.exe uitvoert in de opdrachtregel, wordt het volgende opgemaakte foutenrapport gegenereerd.

Houd rekening met de overlappende, rode vakken die zeven belangrijke gegevens markeren:

Schermopname van de debugger met een eenvoudige globale overloopfout.

Rode markeringen, van boven naar beneden

  1. De geheugenveiligheidsfout is een wereldwijde buffer-overloop.
  2. Er zijn 4 bytes (32 bits) opgeslagen buiten een door de gebruiker gedefinieerde variabele.
  3. De opslag vond plaats in functie main() gedefinieerd in bestand basic-global-overflow.cpp op regel 7.
  4. De benoemde x variabele wordt gedefinieerd in basic-global-overflow.cpp op regel 3, beginnend bij kolom 8.
  5. Deze globale variabele x heeft een grootte van 400 bytes.
  6. De exacte shadow-byte die het adres beschreef waarop de schrijfactie was gericht, had een waarde van 0xf9.
  7. De shadowbyte-legenda geeft aan dat 0xf9 een opvulgebied is dat zich rechts van int x[100] bevindt.

Notitie

Wanneer AddressSanitizer een fout rapporteert, roept de ASan-runtime de LLVM-symboliek aan om de functienamen in de aanroepstack te produceren.

AddressSanitizer gebruiken in Visual Studio

AddressSanitizer is geïntegreerd met de Visual Studio IDE. Als u AddressSanitizer wilt inschakelen voor een MSBuild-project, klikt u met de rechtermuisknop op het project in Solution Explorer en kiest u Eigenschappen. Selecteer in het dialoogvenster eigenschappenpagina'sconfiguratie-eigenschappen>C/C++>Algemeenen wijzig vervolgens de eigenschap AddressSanitizer inschakelen. Kies OK- om uw wijzigingen op te slaan.

Schermopname van het dialoogvenster Eigenschapspagina's die de eigenschap AddressSanitizer inschakelen toont.

Als u wilt bouwen vanuit de IDE, moet u zich afmelden voor incompatibele opties. Voor een bestaand project dat is gecompileerd met behulp van /Od (of de foutopsporingsmodus), moet u mogelijk deze opties uitschakelen:

Druk op F5om het foutopsporingsprogramma te bouwen en uit te voeren. In Visual Studio verschijnt er een venster met de mededeling uitzondering opgetreden.

Schermopname van het foutopsporingsprogramma met een globale bufferoverloopfout.

AddressSanitizer gebruiken vanuit Visual Studio: CMake

Voer de volgende stappen uit om AddressSanitizer in te schakelen voor een CMake-project dat is gemaakt voor Windows:

  1. Open het vervolgkeuzemenu Configuraties in de werkbalk boven aan de IDE en selecteer Configuraties beheren.

    Schermopname van het vervolgkeuzemenu CMake-configuratie met opties zoals x64 Debug, x64 Release en, onder aan de lijst, Configuraties beheren... is gemarkeerd.

    Met deze actie opent u de editor instellingen van CMake Project, die de inhoud van het bestand CMakeSettings.json van uw project weerspiegelt.

  2. Kies de link JSON bewerken. Met deze selectie wordt de weergave overgeschakeld naar onbewerkte JSON.

  3. Als u AddressSanitizer wilt inschakelen, voegt u het volgende fragment toe aan de "windows-base" voorinstelling, in "configurePresets":.

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

    "configurePresets" ziet er daarna ongeveer als volgt uit:

        "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 werkt niet als bewerken en doorgaan is opgegeven (/ZI), wat standaard is ingeschakeld voor nieuwe CMake-projecten. Markeer in CMakeLists.txt de regel die begint met # als commentaar door een voorvoegsel met set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT" toe te voegen. Deze lijn ziet er ongeveer als volgt uit:

    # 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. Gebruik Ctrl+S om dit JSON-bestand op te slaan.

  6. Wis de map van de CMake-cache en configureer opnieuw door een keuze te maken in het Menu van Visual Studio: Project>Cache verwijderen enopnieuw configureren. Kies Ja wanneer de prompt wordt weergegeven om uw cachemap te wissen en opnieuw te configureren.

  7. Vervang bijvoorbeeld de inhoud van het bronbestand CMakeProject1.cppdoor de volgende code:

    // 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. Kies F5- om opnieuw te compileren en uit te voeren onder het foutopsporingsprogramma.

    In deze schermopname wordt de fout van de CMake-build vastgelegd.

    Schermafbeelding met een uitzondering met de melding: AddressSanitizer-fout: globale bufferoverloop.

AddressSanitizer-crashdumps

AddressSanitizer bevat functionaliteit voor gebruik met cloud- en gedistribueerde werkstromen. Met deze functionaliteit kan een AddressSanitizer-fout offline worden weergegeven in de IDE. De fout wordt over je bron heen gelegd, net zoals je dat zou ervaren in een live debugsessie.

Deze dumpbestanden kunnen leiden tot efficiëntie wanneer u een fout analyseert. Je hoeft niets opnieuw uit te voeren, geen gegevens op afstand op te sporen of te zoeken naar een machine die offline is gegaan.

Als u een dumpbestand wilt maken dat u op een later tijdstip kunt bekijken in Visual Studio op een andere computer:

set ASAN_SAVE_DUMPS=MyFileName.dmp

Vanaf Visual Studio 16.9 kunt u a nauwkeurig opgegeven fout weergeven, opgeslagen in uw *.dmp-bestand, boven op uw broncode.

Deze crashdumpfunctionaliteit maakt cloudwerkstromen of gedistribueerde tests mogelijk. Het kan ook worden gebruikt voor het indienen van een gedetailleerde, bruikbare fout in elk scenario.

Voorbeeldfouten

AddressSanitizer kan verschillende soorten misbruik van geheugen detecteren. Hier volgen veel runtimefouten die worden gerapporteerd wanneer u de binaire bestanden uitvoert die zijn gecompileerd met behulp van de optie AddressSanitizer (/fsanitize=address) compiler:

Zie AddressSanitizer-foutvoorbeeldenvoor meer informatie over de voorbeelden.

Verschillen met Clang 12.0

MSVC verschilt momenteel van Clang 12.0 in twee functionele gebieden:

  • stack-use-after-scope: deze instelling is standaard ingeschakeld en kan niet worden uitgeschakeld.
  • stack-use-after-return: deze functionaliteit vereist een extra compileroptie en is niet beschikbaar door alleen in te stellen ASAN_OPTIONS.

Deze beslissingen zijn genomen om de testmatrix te verminderen die nodig is om deze eerste versie te leveren.

Functies die tot valse positieven kunnen leiden in Visual Studio 2019 16.9 zijn niet opgenomen. Deze discipline dwingt de effectieve testintegriteit af die nodig is bij het overwegen van interop met tientallen jaren bestaande code. In latere releases kunnen meer mogelijkheden worden overwogen:

Zie Building for AddressSanitizer met MSVCvoor meer informatie.

Documentatie voor de branche

Er bestaat uitgebreide documentatie voor deze taal- en platformafhankelijke implementaties van de AddressSanitizer-technologie.

In dit seminale document over de AddressSanitizer (extern) wordt de implementatie beschreven.

Zie ook