Sdílet prostřednictvím


AddressSanitizer

Přehled

Jazyky C & C++ jsou výkonné, ale mohou trpět třídou chyb, které ovlivňují správnost programu a zabezpečení programu. Počínaje sadou Visual Studio 2019 verze 16.9 podporuje kompilátor Microsoft C/C++ (MSVC) a integrované vývojové prostředí ( IDE) sanitizer AddressSanitizer . AddressSanitizer (ASan) je technologie kompilátoru a modulu runtime, která zveřejňuje mnoho těžko najít chyb s nulovými falešně pozitivními výsledky:

Použijte AddressSanitizer ke zkrácení času stráveného na:

  • Základní správnost
  • Přenositelnost napříč platformami
  • Zabezpečení
  • Zátěžové testování
  • Integrace nového kódu

AddressSanitizer, původně představený Společností Google, poskytuje technologie pro vyhledávání chyb za běhu, které používají stávající systémy sestavení a existující testovací prostředky přímo.

AddressSanitizer je integrovaný se systémem projektů sady Visual Studio, se systémem sestavení CMake a integrovaným vývojovým prostředím. Projekty mohou povolit AddressSanitizer nastavením vlastnosti projektu nebo pomocí jedné další možnosti kompilátoru: /fsanitize=address. Nová možnost je kompatibilní se všemi úrovněmi optimalizace a konfigurací x86 a x64. Není však kompatibilní s úpravami a pokračováním, přírůstkovým propojením a /RTC.

Od sady Visual Studio 2019 verze 16.9 technologie AddressSanitizer společnosti Microsoft umožňuje integraci s integrovaným vývojovém prostředím sady Visual Studio. Funkce může volitelně vytvořit soubor s výpisem stavu systému, když sanitizátor najde chybu za běhu. Pokud před spuštěním programu nastavíte ASAN_SAVE_DUMPS=MyFileName.dmp proměnnou prostředí, vytvoří se soubor s výpisem stavu systému s dalšími metadaty pro efektivní následné ladění přesně diagnostikovaných chyb. Tyto soubory s výpisem paměti usnadňují rozšířené použití AddressSanitizeru pro:

  • Místní strojové testování
  • Místní distribuované testování
  • Cloudové pracovní postupy pro testování

Instalace AddressSanitizer

Úlohy C++ v Instalační program pro Visual Studio ve výchozím nastavení nainstalují knihovny AddressSanitizer a integraci integrovaného vývojového prostředí (IDE). Pokud ale upgradujete ze starší verze sady Visual Studio 2019, povolte po upgradu podporu ASan pomocí instalačního programu. Instalační program můžete otevřít z hlavní nabídky sady Visual Studio prostřednictvím nástrojů>Získat nástroje a funkce... V Instalační program pro Visual Studio zvolte Upravit ve stávající instalaci sady Visual Studio, abyste se dostali na následující obrazovku.

Snímek obrazovky s Instalační program pro Visual Studio V části Volitelné je zvýrazněna komponenta C++ AddressSanitizer.

Poznámka:

Pokud visual Studio spustíte v nové aktualizaci, ale nenainstalovali jste ASan, při spuštění kódu se zobrazí chyba:

LNK1356: Nelze najít knihovnu clang_rt.asan_dynamic-i386.lib.

Použití AddressSanitizeru

Začněte vytvářet spustitelné soubory s možností kompilátoru /fsanitize=address pomocí některé z těchto běžných metod vývoje:

  • Sestavení příkazového řádku
  • Projektový systém sady Visual Studio
  • Integrace CMake sady Visual Studio

Znovu zkompilujte a pak program normálně spusťte. Tato generace kódu zveřejňuje mnoho typů přesně diagnostikovaných chyb. Tyto chyby se oznamují třemi způsoby: v integrovaném vývojovém prostředí ladicího programu, na příkazovém řádku nebo uloženém v novém typu souboru s výpisem paměti pro přesné off-line zpracování.

Microsoft doporučuje používat AddressSanitizer v těchto třech standardních pracovních postupech:

Tento článek popisuje informace, které potřebujete k povolení výše uvedených tří pracovních postupů. Informace jsou specifické pro implementaci AddressSanitizer závislé na platformě Windows 10 (a novější). Tato dokumentace doplňuje vynikající dokumentaci od Společnosti Google, Apple a GCC již publikované.

Poznámka:

Podpora je omezená na x86 a x64 ve Windows 10 a novějších verzích. Pošlete nám svůj názor na to, co byste chtěli vidět v budoucích verzích. Vaše zpětná vazba nám pomáhá určit prioritu jiných sanitizátorů pro budoucnost, například /fsanitize=thread, /fsanitize=leak, /fsanitize=memory, /fsanitize=undefinednebo /fsanitize=hwaddress. Pokud narazíte na problémy, můžete zde nahlásit chyby.

Použití AddressSanitizer z příkazového řádku vývojáře

Pomocí možnosti kompilátoru /fsanitize=address na příkazovém řádku vývojáře povolte kompilaci pro modul runtime AddressSanitizer. Možnost /fsanitize=address je kompatibilní se všemi existujícími úrovněmi optimalizace C++ nebo C (například /Od, /O1, /O2, /O2 /GLa PGO). Tato možnost funguje se statickými a dynamickými crty (například /MD, /MDd, /MT, a /MTd). Funguje bez ohledu na to, zda vytváříte EXE nebo DLL. Pro optimální formátování zásobníků volání se vyžadují informace o ladění. V následujícím příkladu cl /fsanitize=address /Zi se předá na příkazovém řádku.

Knihovny AddressSanitizer (soubory .lib) jsou pro vás automaticky propojeny. Další informace naleznete v tématu Jazyk AddressSanitizer, sestavení a ladění reference.

Příklad – základní přetečení globální vyrovnávací paměti

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

Použití příkazového řádku vývojáře pro Visual Studio 2019, kompilace main.cpp pomocí /fsanitize=address /Zi

Snímek obrazovky s příkazovým řádkem zobrazující příkaz pro kompilaci s možnostmi AddressSanitizer Příkaz je: cl main.cpp -faanitize-address /Zi.

Když spustíte výsledek main.exe na příkazovém řádku, vytvoří se následující formátovaná zpráva o chybách.

Zvažte překryvná červená pole, která zvýrazňují sedm klíčových informací:

Snímek obrazovky ladicího programu zobrazující základní chybu globálního přetečení

V sestavě chyb je sedm červených zvýraznění identifikující klíčové informace. Namapují se na číslovaný seznam, který následuje za tímto snímkem obrazovky. Číslovaná pole zvýrazňují následující text: 1) globální přetečení vyrovnávací paměti 2) ZÁPIS o velikosti 4 3) basic-global-overflow.cpp 7 4) napravo od globální proměnné x definované v oblasti "basic-global-overflow.cpp:3:8" 5) velikosti 400 6) 00 00[f9]f9 f9 7) Pole je ve stínové bajtové oblasti legendy a obsahuje globální červené pásmo: f9

Červené zvýraznění shora dolů

  1. Chyba bezpečnosti paměti je globální přetečení vyrovnávací paměti.
  2. Byly uloženy 4 bajty (32 bitů) mimo libovolnou uživatelsky definovanou proměnnou.
  3. Úložiště proběhlo ve funkci main() definované v souboru basic-global-overflow.cpp na řádku 7.
  4. Pojmenovaná proměnná x se definuje v basic-global-overflow.cpp na řádku 3 počínaje sloupcem 8.
  5. Tato globální proměnná x má velikost 400 bajtů.
  6. Přesný stínový bajt popisující adresu cílenou úložištěm měla hodnotu 0xf9
  7. Legenda stínového bajtu říká 0xf9 , že je oblast odsazení napravo odsazení. int x[100]

Poznámka:

Názvy funkcí v zásobníku volání se vytvářejí prostřednictvím symbolizátoru LLVM, který je vyvolán modulem runtime při chybě.

Použití AddressSanitizeru v sadě Visual Studio

AddressSanitizer je integrovaný do integrovaného vývojového prostředí sady Visual Studio. Chcete-li zapnout AddressSanitizer pro projekt MSBuild, klikněte pravým tlačítkem myši na projekt v Průzkumník řešení a zvolte Vlastnosti. V dialogovém okně Stránky vlastností vyberte Vlastnosti>konfigurace C/C++>Obecné a pak upravte vlastnost Enable AddressSanitizer. Kliknutím na OK uložte provedené změny.

Snímek obrazovky dialogového okna Stránky vlastností zobrazující vlastnost Enable AddressSanitizer

Pokud chcete vytvářet z integrovaného vývojového prostředí, odhlaste se z nekompatibilních možností. U existujícího projektu kompilovaného pomocí /Od (nebo režimu ladění) možná budete muset vypnout tyto možnosti:

Ladicí program sestavíte a spustíte stisknutím klávesy F5. V sadě Visual Studio se zobrazí okno vyvolání výjimky:

Snímek obrazovky ladicího programu zobrazující chybu přetečení globální vyrovnávací paměti

Použití AddressSanitizer ze sady Visual Studio: CMake

Chcete-li povolit AddressSanitizer pro projekt CMake vytvořený pro cílový systém Windows, postupujte takto:

  1. Otevřete rozevírací seznam Konfigurace na panelu nástrojů v horní části integrovaného vývojového prostředí a vyberte Spravovat konfigurace.

    Snímek obrazovky s rozevíracím seznamem konfigurace CMake Zobrazuje možnosti, jako je x64 Debug, x64 Release atd. V dolní části seznamu spravovat konfigurace... je zvýrazněná.

    Tím se otevře editor nastavení projektu CMake, který odráží obsah souboru projektu CMakeSettings.json .

  2. V editoru zvolte odkaz Upravit JSON . Tento výběr přepne zobrazení na nezpracovaný formát JSON.

  3. Do přednastaveného "windows-base" nastavení přidejte následující fragment kódu, aby "configurePresets": se zapnula adresa Sanitizer:

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

    "configurePresets" vypadá přibližně takto:

        "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. Sanitizátor adresy nefunguje, pokud je zadán parametr edit-and-continue (/ZI), který je ve výchozím nastavení povolený pro nové projekty CMake. V CMakeLists.txt, okomentovat (předpona #) řádek, který začíná set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"na . Tento řádek vypadá přibližně takto:

    # 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. Pokud chcete uložit tento soubor JSON, zadejte Ctrl+S .

  6. Vymažte adresář mezipaměti CMake a překonfigurujte tak, že zvolíte z nabídky sady Visual Studio: Mezipaměť Pro odstranění projektu>a změna konfigurace. Po zobrazení výzvy zvolte Ano , aby se adresář mezipaměti vymaže a znovu nakonfiguruje.

  7. Obsah zdrojového souboru (například CMakeProject1.cpp) nahraďte následujícím kódem:

    // 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. Zvolte F5 , chcete-li překompilovat a spustit pod ladicím programem.

    Tento snímek obrazovky zachycuje chybu z sestavení CMake.

    Snímek obrazovky s výjimkou: Address Sanitizer Error: Global buffer overflow Na pozadí je výstup sanitizátoru adres viditelný v příkazovém okně.

Výpisy stavu systému AddressSanitizer

V AddressSanitizer jsme zavedli nové funkce pro použití s cloudovými a distribuovanými pracovními postupy. Tato funkce umožňuje offline zobrazení chyby AddressSanitizer v integrovaném vývojovém prostředí (IDE). Chyba se nad zdrojem překryje, stejně jako byste měli zkušenosti v živé ladicí relaci.

Tyto nové soubory s výpisem paměti můžou při analýze chyby vést k efektivitě. Nemusíte znovu sjíždět ani hledat vzdálená data nebo hledat počítač, který se odešel mimo linku.

Pokud chcete vytvořit nový typ souboru s výpisem paměti, který je možné zobrazit v sadě Visual Studio na jiném počítači později:

set ASAN_SAVE_DUMPS=MyFileName.dmp

Počínaje sadou Visual Studio 16.9 můžete zobrazit přesně diagnostickou chybu uloženou v *.dmp souboru nad zdrojovým kódem.

Tato nová funkce výpisu stavu systému umožňuje cloudové pracovní postupy nebo distribuované testování. Dá se také použít k vytvoření podrobné chyby s možností použití v jakémkoli scénáři.

Příklady chyb

AddressSanitizer dokáže rozpoznat několik druhů chyb zneužití paměti. Tady je mnoho chyb modulu runtime hlášených při spuštění binárních souborů zkompilovaných pomocí možnosti kompilátoru AddressSanitizer (/fsanitize=address):

Další informace o příkladech najdete v tématu Příklady chyb AddressSanitizer.

Rozdíly v jazyce Clang 12.0

MSVC se v současné době liší od jazyka Clang 12.0 ve dvou funkčních oblastech:

  • stack-use-after-scope – toto nastavení je ve výchozím nastavení zapnuté a nejde ho vypnout.
  • stack-use-after-return – tato funkce vyžaduje další možnost kompilátoru a není dostupná pouze nastavením ASAN_OPTIONS.

Tato rozhodnutí byla provedena, aby se snížila testovací matice potřebná k doručení této první verze.

Funkce, které by mohly vést k falešně pozitivním výsledkům v sadě Visual Studio 2019 16.9, nebyly zahrnuty. Tato disciplína vynucuje efektivní integritu testování potřebnou při zvažování spolupráce s desetiletími stávajícího kódu. V pozdějších verzích je možné zvážit další možnosti:

Další informace naleznete v tématu Building for AddressSanitizer s MSVC.

Stávající oborová dokumentace

Rozsáhlá dokumentace již existuje pro tyto implementace závislé na jazyce a platformě technologie AddressSanitizer.

Tento středník na AddressSanitizer (externí) popisuje implementaci.

Viz také

Známé problémy s addressSanitizerem
Referenční dokumentace k sestavení a jazyku AddressSanitizer
Referenční informace k modulu runtime AddressSanitizer
Stínové bajty AddressSanitizer
AddressSanitizer – cloud nebo distribuované testování
Integrace ladicího programu AddressSanitizer
Příklady chyb AddressSanitizer