AddressSanitizer (AdressSanitierer)

Übersicht

Die C- und 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ützen 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 den 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 festlegen, bevor Sie Ihr Programm ausführen, wird eine Absturzabbilddatei mit zusätzlichen Metadaten erstellt, die ein effizientes Post-Mortem-Debugging präzise diagnostizierter Fehler 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 Visual Studio Hauptmenü öffnen, indem Sie Tools>Get Tools and Features auswählen. Wählen Sie Modify in Ihrer vorhandenen Visual Studio Installation aus dem Visual Studio Installer aus, um zum folgenden Bildschirm zu gelangen.

Screenshot, der den Visual Studio Installer zeigt, wobei die C++-AddressSanitizer-Komponente im Abschnitt „Optional“ hervorgehoben ist.

Hinweis

Wenn Sie Visual Studio für das neue 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:

  • Befehlszeilen-Erstellungen
  • Visual Studio-Projektsystem
  • Visual Studio CMake-Integration

Kompilieren Sie das Programm erneut und führen Sie es dann normalerweise aus. 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 (und höher) von AddressSanitizer. Diese Dokumentation ergänzt die bereits veröffentlichte hervorragende Dokumentation von Google, Apple und GCC.

Hinweis

Die Unterstützung ist auf x86 und x64 unter Windows 10 und höher 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. B. /fsanitize=thread, /fsanitize=leak, /fsanitize=memory, /fsanitize=undefined oder /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 vorhandenen C++- oder C-Optimierungsstufen kompatibel, beispielsweise /Od, /O1, /O2 und /O2 /GL. Die Option funktioniert mit statischen und dynamischen CRTs (z. B. /MD, /MDd, /MT und /MTd). Es funktioniert, ob Sie eine EXE- oder DLL-Datei erstellen. Debuginformationen sind für eine optimale Formatierung von Aufrufstapeln erforderlich. Im folgenden Beispiel wird cl /fsanitize=address /Zi in der Befehlszeile übergeben.

Hinweis

AddressSanitizer unterstützt keine profilgeführte Optimierung (Profile-guided optimization, PGO). AddressSanitizer sollte nicht in der Produktion verwendet werden.

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 Sie basic-global-overflow.cpp mithilfe einer Entwickler-Eingabeaufforderung für Visual Studio 2019 mit /fsanitize=address /Zi.

Screenshot einer Eingabeaufforderung mit dem Befehl

Wenn Sie das Ergebnis basic-global-overflow.exe an der Befehlszeile ausführen, wird der folgende formatierte Fehlerbericht erstellt.

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

Bildschirmaufnahme des Debuggers, die einen grundlegenden globalen Überlauffehler zeigt.

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 Store fand in der Funktion main() statt, die in Datei basic-global-overflow.cpp in Zeile 7 definiert ist.
  4. Die benannte x Variable wird in basic-global-overflow.cpp in Zeile 3 ab Spalte 8 definiert.
  5. Diese globale Variable x hat eine Größe von 400 Bytes.
  6. Das genaue Schattenbyte , das die Adresse beschreibt, die vom Speicher adressiert wurde, hatte einen Wert von 0xf9.
  7. Die Schattenbyte-Legende besagt, dass 0xf9 ein Auffüllbereich rechts von int x[100] ist.

Hinweis

Wenn AddressSanitizer einen Fehler meldet, ruft die ASan-Laufzeit den LLVM-Symboler auf, um die Funktionsnamen im Aufrufstapel zu erzeugen.

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 des Eigenschaftenseiten-Dialogs mit der Eigenschaft

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

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

Screenshot des Debuggers mit einem globalen Pufferüberlauffehler.

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 das Dropdownmenü "Konfigurationen" in der Symbolleiste am oberen Rand der IDE, und wählen Sie " Konfigurationen verwalten" aus.

    Screenshot des Dropdownmenüs

    Diese Aktion öffnet den CMake Project Einstellungs-Editor, der den Inhalt der datei CMakeSettings.json Ihres project widerspiegelt.

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

  3. Um AddressSanitizer zu aktivieren, fügen Sie den folgenden Codeausschnitt zur Voreinstellung "windows-base" innerhalb von "configurePresets": hinzu.

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

    "configurePresets" sieht danach ungefähr so 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. AddressSanitizer funktioniert nicht, wenn "Edit-and-continue" angegeben ist (/ZI), das standardmäßig für neue CMake-Projekte aktiviert ist. Kommentieren Sie die Zeile in CMakeLists.txt, die mit # beginnt, indem Sie set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT" davor setzen. 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. Verwenden 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 beispielsweise CMakeProject1.cppdurch den folgenden 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. 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 mit einer Ausnahme mit folgendem Text: AddressSanitizer-Fehler: globaler Pufferüberlauf.

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 über Ihrem Quellcode angezeigt, so wie Sie es in einer Live-Debug-Sitzung erleben würden.

Diese neuen Speicherabbilddateien können zu Effizienzsteigerungen führen, wenn Sie einen Fehler analysieren. Sie müssen den Vorgang nicht erneut ausführen, keine Remotedaten abrufen oder nach einem Gerät suchen, das offline gegangen ist.

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 einen präzise diagnostizierten Fehler, der in Ihrer *.dmp-Datei gespeichert ist, über Ihrem Quellcode anzeigen.

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 für die Interoperabilität mit seit Jahrzehnten bestehendem Code erforderlich ist. Weitere Funktionen können in späteren Versionen berücksichtigt werden:

Weitere Informationen finden Sie unter Entwickeln für AddressSanitizer mit 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 (extern) wird die Implementierung beschrieben.

Siehe auch