AddressSanitizer

Überblick

Die C & C++-Sprachen sind leistungsfähig, können aber unter einer Klasse von Fehlern leiden, die die Programmkorrektur und Programmsicherheit beeinflussen. Ab Visual Studio 2019, Version 16.9, unterstützt der Microsoft C/C++-Compiler (MSVC) und die IDE den AddressSanitizer-Sanitizer . AddressSanitizer (ASan) ist eine Compiler- und Laufzeittechnologie, die viele schwer zu findende Fehler mit null falsch positiven Ergebnissen verfügbar macht:

Verwenden Sie AddressSanitizer, um Ihre Zeitaufwand zu reduzieren:

  • Grundlegende Korrektheit
  • Plattformübergreifende Portabilität
  • Sicherheit
  • Belastungstest
  • Integrieren von neuem Code

AddressSanitizer, ursprünglich von Google eingeführt, bietet Laufzeit-Fehlersuche-Technologien, die Ihre vorhandenen Buildsysteme und vorhandene Testressourcen direkt verwenden.

AddressSanitizer ist in das Visual Studio-Projektsystem, das CMake-Buildsystem und die IDE integriert. Projekte können AddressSanitizer aktivieren, indem sie eine Projekteigenschaft festlegen oder eine zusätzliche Compileroption verwenden: /fsanitize=address. Die neue Option ist mit allen Optimierungs- und Konfigurationsebenen von x86 und x64 kompatibel. Es ist jedoch nicht kompatibel mit "Edit-and-continue", "inkrementelle Verknüpfung" und /RTC".

Ab Visual Studio 2019, Version 16.9, ermöglicht die AddressSanitizer-Technologie von Microsoft die Integration in die Visual Studio-IDE. Die Funktionalität kann optional eine Absturzabbilddatei erstellen, wenn der Sanitizer zur Laufzeit einen Fehler findet. Wenn Sie die ASAN_SAVE_DUMPS=MyFileName.dmp Umgebungsvariable vor dem Ausführen des Programms festlegen, wird eine Absturzabbilddatei mit zusätzlichen Metadaten erstellt, um das effiziente Debuggen nach der Mortem-Analyse präzise diagnostizierter Fehler zu ermöglichen. Diese Dumpdateien vereinfachen die erweiterte Verwendung von AddressSanitizer für:

  • Testen lokaler Computer
  • Lokale verteilte Tests
  • Cloudbasierte Workflows zum Testen

Installieren von AddressSanitizer

C++-Workloads im Visual Studio-Installer standardmäßig die AddressSanitizer-Bibliotheken und die IDE-Integration installieren. Wenn Sie jedoch ein Upgrade von einer älteren Version von Visual Studio 2019 durchführen, verwenden Sie das Installationsprogramm, um die ASan-Unterstützung nach dem Upgrade zu aktivieren. Sie können das Installationsprogramm über das Menü "Visual Studio Standard" über "Extras>und Features abrufen" öffnen... Wählen Sie "Ändern" für Ihre vorhandene Visual Studio-Installation aus dem Visual Studio-Installer aus, um zum folgenden Bildschirm zu gelangen.

Screenshot of the Visual Studio Installer. The C++ AddressSanitizer component, under the Optional section, is highlighted.

Hinweis

Wenn Sie Visual Studio auf dem neuen Update ausführen, aber ASan nicht installiert haben, wird beim Ausführen des Codes eine Fehlermeldung angezeigt:

LNK1356: Bibliothek "clang_rt.asan_dynamic-i386.lib" wurde nicht gefunden.

Verwenden von AddressSanitizer

Beginnen Sie mit dem Erstellen Ihrer ausführbaren Dateien mit der /fsanitize=address Compileroption, indem Sie eine der folgenden allgemeinen Entwicklungsmethoden verwenden:

  • Befehlszeilenbuilds
  • Visual Studio-Projektsystem
  • Visual Studio CMake-Integration

Kompilieren Sie das Programm dann normal. Diese Codegenerierung macht viele Arten genau diagnostizierter Fehler verfügbar. Diese Fehler werden auf drei Arten gemeldet: in der Debugger-IDE, in der Befehlszeile oder in einem neuen Speicherabbilddateityp für eine präzise Offlineverarbeitung.

Microsoft empfiehlt die Verwendung von AddressSanitizer in diesen drei Standardworkflows:

In diesem Artikel werden die Informationen behandelt, die Sie benötigen, um die drei zuvor aufgeführten Workflows zu aktivieren. Die Informationen sind spezifisch für die plattformabhängige Windows 10-Implementierung von AddressSanitizer. Diese Dokumentation ergänzt die hervorragende Dokumentation von Google, Apple und GCC bereits veröffentlicht.

Hinweis

Die aktuelle Unterstützung ist auf x86 und x64 unter Windows 10 beschränkt. Senden Sie uns Feedback dazu, was Sie in zukünftigen Versionen sehen möchten. Ihr Feedback hilft uns, andere Bereinigungsmittel für die Zukunft zu priorisieren, z /fsanitize=thread. B. , , /fsanitize=leak, /fsanitize=memory, /fsanitize=undefinedoder /fsanitize=hwaddress. Sie können hier Fehler melden, wenn Probleme auftreten.

Verwenden von AddressSanitizer über eine Entwickler-Eingabeaufforderung

Verwenden Sie die /fsanitize=address Compileroption in einer Entwickler-Eingabeaufforderung , um die Kompilierung für die AddressSanitizer-Laufzeit zu aktivieren. Die /fsanitize=address Option ist mit allen vorhandenen C++- oder C-Optimierungsstufen kompatibel (z/Od. B. , , /O1, /O2, und /O2 /GLPGO). Die Option funktioniert mit statischen und dynamischen CRTs (z /MD. B. , , /MDd, /MTund /MTd). Es funktioniert, ob Sie eine EXE- oder DLL-Datei erstellen. Debuginformationen sind für eine optimale Formatierung von Aufrufstapeln erforderlich. Im folgenden Beispiel cl /fsanitize=address /Zi wird die Befehlszeile übergeben.

Die AddressSanitizer-Bibliotheken (LIB-Dateien) werden automatisch verknüpft. Weitere Informationen finden Sie unter AddressSanitizer-Sprache, Build- und Debuggingreferenz.

Beispiel : einfacher globaler Pufferüberlauf

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

Kompilieren main.cpp mithilfe einer Entwickler-Eingabeaufforderung für Visual Studio 2019 /fsanitize=address /Zi

Screenshot of a command prompt showing the command to compile with AddressSanitizer options. The command is: `cl main.cpp -faanitize-address /Zi`.

Wenn Sie das Ergebnis main.exe an der Befehlszeile ausführen, wird der folgende formatierte Fehlerbericht erstellt.

Betrachten Sie die überlagerten roten Felder, die sieben wichtige Informationen hervorheben:

Screenshot of the debugger showing a basic global overflow error.

Es gibt sieben rote Highlights, die wichtige Informationen im Fehlerbericht identifizieren. Sie werden der nummerierten Liste zugeordnet, die diesem Screenshot folgt. Die nummerierten Felder markieren den folgenden Text: 1) global-buffer-overflow 2) WRITE of size 4 3) basic-global-overflow.cpp 7 4) rechts von der globalen Variablen "x", die in "basic-global-global-definiert" definiert ist overflow.cpp:3:8' 5) von Größe 400 6) 00 00[f9]f9 f9 7) Box befindet sich im Bereich der Schattenbytelegende und enthält globale Redzone: f9

Rote Hervorhebungen von oben nach unten

  1. Der Speichersicherheitsfehler ist ein globaler Pufferüberlauf.
  2. Außerhalb einer benutzerdefinierten Variablen wurden 4 Bytes (32 Bit) gespeichert .
  3. Der Speicher wurde in Der Datei main() in Zeile basic-global-overflow.cpp 7 definiert.
  4. Die benannte x Variable wird in Zeile 3 ab Spalte 8 in basic-global-overflow.cpp definiert.
  5. Diese globale Variable x hat eine Größe von 400 Byte.
  6. Das genaue Schattenbyte , das die Adresse beschreibt, auf die der Speicher abzielt, hat einen Wert von 0xf9
  7. Die Schattenbytelegende sagt, 0xf9 dass es sich um einen Bereich mit Abstand rechts von int x[100]

Hinweis

Die Funktionsnamen im Aufrufstapel werden über den LLVM-Symboler erzeugt, der von der Laufzeit beim Fehler aufgerufen wird.

Verwenden von AddressSanitizer in Visual Studio

AddressSanitizer ist in die Visual Studio-IDE integriert. Um AddressSanitizer für ein MSBuild-Projekt zu aktivieren, klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie "Eigenschaften" aus. Wählen Sie im Dialogfeld "Eigenschaftenseiten" die Option "Konfigurationseigenschaften>C/C++>Allgemein" aus, und ändern Sie dann die Eigenschaft "AddressSanitizer aktivieren". Klicken Sie auf OK, um die Änderungen zu speichern.

Screenshot of the Property Pages dialog showing the Enable AddressSanitizer property.

Um aus der IDE zu erstellen, deaktivieren Sie alle inkompatiblen Optionen. Für ein vorhandenes Projekt, das mithilfe des /Od (oder Debugmodus) kompiliert wurde, müssen Sie diese Optionen möglicherweise deaktivieren:

Drücken Sie F5, um den Debugger zu erstellen und auszuführen. Ein Fenster "Ausnahme ausgelöst " wird in Visual Studio angezeigt:

Screenshot of the debugger showing a global buffer overflow error.

Verwenden von AddressSanitizer aus Visual Studio: CMake

Führen Sie die folgenden Schritte aus, um AddressSanitizer für ein für Windows erstelltes CMake-Projekt zu aktivieren:

  1. Öffnen Sie die Dropdownliste "Konfigurationen" in der Symbolleiste am oberen Rand der IDE, und wählen Sie "Konfigurationen verwalten" aus.

    Screenshot of the CMake configuration dropdown. It displays options like x64 Debug, x64 Release, and so on. At the bottom of the list, Manage Configurations... is highlighted.

    Dadurch wird der CMake Project Einstellungen Editor geöffnet, der den Inhalt der Projektdatei CMakeSettings.json widerspiegelt.

  2. Wählen Sie den JSON-Link bearbeiten im Editor aus. Diese Auswahl wechselt die Ansicht in unformatierte JSON.This selection switches the view to raw JSON.

  3. Fügen Sie den folgenden Codeausschnitt zur Voreinstellung hinzu, um "configurePresets": die "windows-base" Adressbereinigung zu aktivieren:

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

    "configurePresets" sieht wie folgt aus:

        "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. Adressbereinigung funktioniert nicht, wenn "Bearbeiten und Fortsetzen" angegeben ist (/ZI), das standardmäßig für neue CMake-Projekte aktiviert ist. Kommentieren CMakeLists.txtSie in , kommentieren (Präfix mit #) die Zeile, die mit set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT". Diese Zeile sieht ungefähr wie folgt aus:

    # 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. Drücken Sie STRG+S , um diese JSON-Datei zu speichern.

  6. Löschen Sie das CMake-Cacheverzeichnis, und konfigurieren Sie es neu, indem Sie im Menü "Visual Studio" die Option "Cache>löschen" und "Neu konfigurieren" auswählen. Wählen Sie "Ja " aus, wenn die Eingabeaufforderung angezeigt wird, um das Cacheverzeichnis zu löschen und neu zu konfigurieren.

  7. Ersetzen Sie den Inhalt der Quelldatei (z. B CMakeProject1.cpp. ) durch Folgendes:

    // 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. Wählen Sie F5 aus, um das Kompilieren neu zu kompilieren und unter dem Debugger auszuführen.

    Dieser Screenshot erfasst den Fehler aus dem CMake-Build.

    Screenshot of an exception that says: Address Sanitizer Error: Global buffer overflow. In the background, address sanitizer output is visible in command window.

AddressSanitizer-Absturzabbilder

Wir haben neue Funktionen in AddressSanitizer für die Verwendung mit Cloud- und verteilten Workflows eingeführt. Diese Funktionalität ermöglicht die Offlineanzeige eines AddressSanitizer-Fehlers in der IDE. Der Fehler wird oben in der Quelle überlagert, genau wie in einer Live-Debugsitzung.

Diese neuen Speicherabbilddateien können bei der Analyse eines Fehlers zu Effizienz führen. Sie müssen keine Remotedaten erneut ausführen oder nach einem Computer suchen, der offline war.

So erstellen Sie eine neue Art von Dumpdatei, die in Visual Studio zu einem späteren Zeitpunkt auf einem anderen Computer angezeigt werden kann:

set ASAN_SAVE_DUMPS=MyFileName.dmp

Ab Visual Studio 16.9 können Sie oben im Quellcode einen genau diagnostizierten Fehler anzeigen, der in Ihrer *.dmp Datei gespeichert ist.

Diese neue Absturzabbildfunktion ermöglicht cloudbasierte Workflows oder verteilte Tests. Es kann auch verwendet werden, um einen detaillierten, umsetzbaren Fehler in jedem Szenario zu speichern.

Beispielfehler

AddressSanitizer kann verschiedene Arten von Speichermissbrauchsfehlern erkennen. Im Folgenden werden viele der Laufzeitfehler gemeldet, wenn Sie ihre Binärdateien mithilfe der Compileroption AddressSanitizer (/fsanitize=address) kompiliert ausführen:

Weitere Informationen zu den Beispielen finden Sie unter AddressSanitizer-Fehlerbeispiele.

Unterschiede bei Clang 12.0

MSVC unterscheidet sich derzeit von Clang 12.0 in zwei Funktionsbereichen:

  • stack-use-after-scope - diese Einstellung ist standardmäßig aktiviert und kann nicht deaktiviert werden.
  • stack-use-after-return - diese Funktionalität erfordert eine zusätzliche Compileroption und ist nicht nur durch Festlegen ASAN_OPTIONSverfügbar.

Diese Entscheidungen wurden getroffen, um die für die Bereitstellung dieser ersten Version erforderliche Testmatrix zu reduzieren.

Features, die zu falsch positiven Ergebnissen in Visual Studio 2019 16.9 führen könnten, wurden nicht einbezogen. Diese Disziplin hat die effektive Testintegrität erzwungen, die bei der Interoperabilität mit jahrzehnten bestehendem Code erforderlich ist. Weitere Funktionen können in späteren Versionen berücksichtigt werden:

Weitere Informationen finden Sie unter Building for AddressSanitizer with MSVC.

Vorhandene Branchendokumentation

Umfangreiche Dokumentationen sind bereits für diese sprach- und plattformabhängigen Implementierungen der AddressSanitizer-Technologie vorhanden.

In diesem seminalen Dokument zum AddressSanitizer wird die Implementierung beschrieben.

Siehe auch

Beheben bekannter Probleme mit demSanitizer
AddressSanitizer Build- und Sprachreferenz
AddressSanitizer-Laufzeitreferenz
AddressSanitizer-Schattenbytes
AddressSanitizer-Cloud oder verteilte Tests
AddressSanitizer Debugger-Integration
Beispiele für AddressSanitizer-Fehler