Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Omówienie
Języki C i C++ są zaawansowane, ale mogą cierpieć na klasę usterek, które wpływają na poprawność programu i zabezpieczenia programu. Począwszy od Visual Studio 2019 w wersji 16.9, kompilator Microsoft C/C++ (MSVC) i środowisko IDE obsługują AddressSanitizer sanitizer. AddressSanitizer (ASan) to technologia kompilatora i środowiska uruchomieniowego, która uwidacznia wiele trudnych do znalezienia błędów z zerowymi wynikami fałszywie dodatnimi:
-
Rozbieżności przy alloc/dealloc oraz
new/deleteniezgodności typów - Alokacje za duże dla sterty
-
callocprzepełnienie iallocaprzepełnienie - Podwójne zwolnienie i użycie po zwolnieniu
- Przepełnienie zmiennej globalnej
- Przepełnienie buforu stert
- Nieprawidłowe wyrównanie wyrównanych wartości
-
memcpyistrncatnakładanie się parametrów - Przepełnienie i niedopełnienie buforu stosu
-
Użycie stosu po
returni użyciu po zakończeniu zakresu - Użycie pamięci po jej zanieczyszczeniu
Dlaczego warto używać narzędzia AddressSanitizer
Użyj narzędzia AddressSanitizer, aby skrócić czas spędzony na:
- Podstawowa poprawność
- Przenośność międzyplatformowa
- Zabezpieczenia
- Testy obciążeniowe
- Integrowanie nowego kodu
AddressSanitizer, pierwotnie wprowadzony przez firmę Google, udostępnia technologie znajdowania błędów środowiska uruchomieniowego, które używają istniejących systemów kompilacji i istniejących zasobów testowych bezpośrednio.
Tworzenie integracji i zgodności
AddressSanitizer jest zintegrowany z systemem projektu Visual Studio, systemem kompilacji CMake i środowiskiem IDE. Projekty mogą włączać metodę AddressSanitizer, ustawiając właściwość projektu lub używając jednej dodatkowej opcji kompilatora: /fsanitize=address. Ta opcja jest zgodna ze wszystkimi poziomami optymalizacji i konfiguracji x86 i x64. Nie jest jednak zgodny z funkcją edytowania i kontynuowania, łączenia przyrostowego i /RTC.
Obsługa zrzutów pamięci
Począwszy od programu Visual Studio 2019 w wersji 16.9 technologia AddressSanitizer firmy Microsoft umożliwia integrację ze środowiskiem IDE programu Visual Studio. Funkcjonalność może opcjonalnie utworzyć zrzut awaryjny, gdy sanitizer znajdzie błąd w trakcie działania. Jeśli ustawisz zmienną ASAN_SAVE_DUMPS=MyFileName.dmp środowiskową przed uruchomieniem programu, zostanie utworzony plik zrzutu awaryjnego z dodatkowymi metadanymi na potrzeby wydajnego debugowania pośmiertnego precyzyjnego diagnozowania usterek. Te pliki zrzutu ułatwiają rozszerzone korzystanie z narzędzia AddressSanitizer:
- Testowanie maszyn lokalnych
- Lokalne testowanie rozproszone
- Przepływy pracy oparte na chmurze na potrzeby testowania
Instalowanie narzędzia AddressSanitizer
Zestawy robocze C++ w Instalatorze programu Visual Studio domyślnie instalują biblioteki AddressSanitizer i integrację z IDE. Jeśli jednak uaktualniasz starszą wersję programu Visual Studio 2019, użyj Instalatora, aby włączyć obsługę aplikacji ASan po uaktualnieniu. Instalator można otworzyć z menu głównego Visual Studio, wybierając pozycję Tools>Pobierz narzędzia i funkcje. Wybierz Modify w istniejącej instalacji Visual Studio z instalatora Visual Studio, aby przejść do następującego ekranu.
Uwaga
Jeśli uruchomisz Visual Studio w nowej aktualizacji, ale nie zainstalowano rozwiązania ASan, podczas uruchamiania kodu wystąpi błąd:
LNK1356: nie można odnaleźć biblioteki "clang_rt.asan_dynamic-i386.lib"
Używanie narzędzia AddressSanitizer
Rozpocznij tworzenie plików wykonywalnych przy użyciu opcji kompilatora /fsanitize=address przy użyciu dowolnej z tych typowych metod programowania:
- Budowanie z linii poleceń
- System projektu programu Visual Studio
- Integracja narzędzia CMake programu Visual Studio
Ponownie skompiluj kod, a następnie uruchom program normalnie, aby uwidocznić wiele typów dokładnie zdiagnozowanych usterek. Możesz przejrzeć problemy w środowisku IDE debugera, wierszu polecenia lub pliku zrzutu.
Firma Microsoft zaleca używanie narzędzia AddressSanitizer w tych trzech standardowych przepływach pracy:
Pętla wewnętrzna programisty
- Visual Studio — wiersz polecenia
- Visual Studio — system projektu
- Visual Studio — CMake
CI/CD - ciągła integracja i ciągłe dostarczanie
- Raportowanie błędów — pliki zrzutu narzędzia AddressSanitizer
Fuzzing - kompilowanie z użyciem osadki libFuzzer
- Azure OneFuzz
- Komputer lokalny
W tym artykule opisano informacje wymagane do włączenia trzech wymienionych wcześniej przepływów pracy. Informacje są specyficzne dla implementacji AddressSanitizer zależnej od platformy w systemie Windows 10 (i nowszych). Ta dokumentacja uzupełnia dokumentację firmy Google, Apple i GCC.
Uwaga
Obsługa jest ograniczona do wersji x86 i x64 w systemie Windows 10 lub nowszym.
Wyślij nam opinię na temat tego, co chcesz zobaczyć w przyszłych wersjach. Twoja opinia pomaga nam określić priorytety innych środków dezynfekujących na przyszłość, takich jak /fsanitize=thread, /fsanitize=leak, /fsanitize=memory, /fsanitize=undefined lub /fsanitize=hwaddress. Jeśli wystąpią problemy, możesz zgłosić usterki w tym miejscu .
Używanie narzędzia AddressSanitizer z wiersza polecenia dewelopera
Użyj opcji kompilatora /fsanitize=address w wierszu polecenia programisty, aby włączyć kompilowanie dla środowiska uruchomieniowego AddressSanitizer. Opcja /fsanitize=address jest zgodna z istniejącymi poziomami optymalizacji dla języka C++ lub C, na przykład /Od, /O1, /O2 i /O2 /GL. Opcja działa ze statycznymi i dynamicznymi CRT (na przykład /MD, /MDd, /MT, i /MTd). Działa niezależnie od tego, czy tworzysz plik EXE, czy bibliotekę DLL. Informacje debugowania są wymagane do optymalnego formatowania stosów wywołań. W poniższym przykładzie cl /fsanitize=address /Zi jest przekazywany w linii poleceń.
Uwaga
Narzędzie AddressSanitizer nie obsługuje optymalizacji opartej na profilu (PGO). Narzędzie AddressSanitizer nie powinno być używane w środowisku produkcyjnym.
Biblioteki AddressSanitizer (pliki .lib) są automatycznie linkowane. Aby uzyskać więcej informacji, zobacz AddressSanitizer language, build, and debug reference (Informacje o języku AddressSanitizer, kompilacji i debugowaniu).
Przykład — przepełnienie podstawowego buforu globalnego
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Przy użyciu wiersza polecenia dewelopera dla Visual Studio 2019 r. skompiluj basic-global-overflow.cpp używając /fsanitize=address /Zi.
Po uruchomieniu wynikowego basic-global-overflow.exe w wierszu polecenia tworzy sformatowany raport o błędach, który jest pokazany poniżej.
Rozważ nakładane, czerwone pola, które podkreślają siedem kluczowych informacji:
Czerwone podświetlenia, od góry do dołu
- Usterka bezpieczeństwa pamięci to globalne przepełnienie bufora.
- Było 4 bajty (32 bity) przechowywane poza dowolną zmienną zdefiniowaną przez użytkownika.
- Zapis miał miejsce w funkcji
main()zdefiniowanej w plikubasic-global-overflow.cppna linii 7. - Zmienna o nazwie
xjest definiowana w basic-global-overflow.cpp w wierszu 3, zaczynając od kolumny 8. - Ta zmienna
xglobalna ma rozmiar 400 bajtów. - Dokładny bajt cienia opisujący adres docelowy magazynu miał wartość
0xf9. - Legenda bajtów cienia wskazuje, że
0xf9oznacza obszar wypełnienia po prawej stronieint x[100].
Uwaga
Gdy narzędzie AddressSanitizer zgłasza błąd, środowisko uruchomieniowe ASan wywołuje symbol LLVM w celu utworzenia nazw funkcji w stosie wywołań.
Używanie narzędzia AddressSanitizer w programie Visual Studio
AddressSanitizer jest zintegrowany ze środowiskiem IDE programu Visual Studio. Aby włączyć funkcję AddressSanitizer dla projektu MSBuild, kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz Właściwości. W oknie dialogowym Strony Właściwości wybierz Właściwości konfiguracji>C/C++>Ogólne, a następnie zmodyfikuj właściwość Enable AddressSanitizer. Wybierz przycisk OK , aby zapisać zmiany.
Aby skompilować z poziomu środowiska IDE, zrezygnuj z wszelkich niezgodnych opcji. W przypadku istniejącego projektu skompilowanego przy użyciu /Od (lub trybu debugowania) może być konieczne wyłączenie następujących opcji:
- Wyłącz
/ZI(Format Informacji Debugowania) - Wyłącz
/RTC1(testy środowiska uruchomieniowego) - Wyłącz
/INCREMENTAL(łączenie przyrostowe)
Aby skompilować i uruchomić debuger, naciśnij F5. W programie Visual Studio pojawi się okno rzucenia wyjątku:
Użyj narzędzia AddressSanitizer z poziomu programu Visual Studio: CMake
Aby włączyć narzędzie AddressSanitizer dla projektu CMake utworzonego dla systemu Windows, wykonaj następujące kroki:
Otwórz menu rozwijane Konfiguracje na pasku narzędzi w górnej części środowiska IDE i wybierz pozycję Zarządzaj konfiguracjami.
Ta akcja otwiera edytor ustawień projektu CMake, który odzwierciedla zawartość pliku
CMakeSettings.jsonTwojego projektu.Wybierz link Edytuj kod JSON . To zaznaczenie przełącza widok na nieprzetworzone dane JSON.
Aby włączyć AddressSanitizer, dodaj następujący fragment do ustawienia wstępnego
"windows-base", wewnątrz"configurePresets":."environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }"configurePresets"wygląda mniej więcej tak: następnie"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" } },Narzędzie AddressSanitizer nie działa, jeśli określono opcję edytuj i kontynuuj (
/ZI), która jest domyślnie włączona dla nowych projektów CMake. WCMakeLists.txtwykomentuj (poprzedź#) wiersz rozpoczynający się odset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT". Ten wiersz wygląda mniej więcej tak:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")Użyj klawiszy Ctrl+S , aby zapisać ten plik JSON.
Wyczyść katalog pamięci podręcznej CMake i skonfiguruj ponownie, wybierając z menu programu Visual Studio: Project>Usuń pamięć podręczną i ponownie skonfiguruj. Wybierz pozycję Tak , gdy zostanie wyświetlony monit, aby wyczyścić katalog pamięci podręcznej i ponownie skonfigurować.
Zastąp zawartość pliku źródłowego, na przykład
CMakeProject1.cpp, następującym kodem:// 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; }Wybierz F5 , aby ponownie skompilować i uruchomić w debugerze.
Ten zrzut ekranu przechwytuje błąd z kompilacji narzędzia CMake.
Zrzuty pamięci narzędzia AddressSanitizer
AddressSanitizer zawiera funkcje do użycia z chmurowymi i rozproszonymi przepływami pracy. Ta funkcja umożliwia wyświetlanie w trybie offline błędu AddressSanitizer w środowisku IDE. Błąd jest nakładany na źródło, podobnie jak w przypadku sesji debugowania na żywo.
Te pliki zrzutu mogą prowadzić do zwiększenia wydajności podczas analizowania usterki. Nie musisz ponownie uruchamiać, znajdować danych zdalnych ani wyszukiwać maszyny, która przeszła w tryb offline.
Aby utworzyć plik zrzutu, który można wyświetlić w Visual Studio na innej maszynie w późniejszym terminie:
set ASAN_SAVE_DUMPS=MyFileName.dmp
Od wersji Visual Studio 16.9 można wyświetlić precyzyjnie zdiagnozowany błąd, zapisany w pliku *.dmp, bezpośrednio w kodzie źródłowym.
Ta funkcja zrzutu awaryjnego umożliwia przepływy pracy oparte na chmurze lub testowanie rozproszone. Może również służyć do zgłaszania szczegółowej usterki, którą można rozwiązać, w dowolnym scenariuszu.
Przykładowe błędy
AddressSanitizer może wykryć kilka rodzajów błędów nieprawidłowego użycia pamięci. Poniżej przedstawiono wiele błędów środowiska uruchomieniowego zgłaszanych podczas uruchamiania plików binarnych skompilowanych przy użyciu opcji kompilatora AddressSanitizer (/fsanitize=address):
alloc-dealloc-mismatchallocation-size-too-bigcalloc-overflowdouble-freedynamic-stack-buffer-overflowglobal-buffer-overflowheap-buffer-overflowheap-use-after-freeinvalid-allocation-alignmentmemcpy-param-overlapnew-delete-type-mismatchstack-buffer-overflowstack-buffer-underflowstack-use-after-returnstack-use-after-scopestrncat-param-overlapuse-after-poison
Aby uzyskać więcej informacji na temat przykładów, zobacz AddressSanitizer error examples (Przykłady błędów AddressSanitizer).
Różnice w Clangu 12.0
Program MSVC obecnie różni się od języka Clang 12.0 w dwóch obszarach funkcjonalnych:
- stack-use-after-scope: to ustawienie jest domyślnie włączone i nie można go wyłączyć.
-
stack-use-after-return: ta funkcjonalność wymaga dodatkowej opcji kompilatora i nie jest dostępna po samym ustawieniu
ASAN_OPTIONS.
Podjęto te decyzje w celu zmniejszenia macierzy testowej wymaganej do dostarczenia tej pierwszej wersji.
Funkcje, które mogą prowadzić do wyników fałszywie dodatnich w programie Visual Studio 2019 16.9, nie zostały uwzględnione. Ta dyscyplina wymuszała efektywną integralność testowania niezbędną podczas rozważania współdziałania z dziesięcioleciami istniejącego kodu. Więcej możliwości można rozważyć w kolejnych wersjach:
- Fiasko kolejnosci inicjalizacji
- Przepełnienie wewnątrz obiektu
- Przepełnienie kontenera
- Odejmowanie/porównanie wskaźników
Aby uzyskać więcej informacji, zobacz Kompilowanie dla AddressSanitizer za pomocą MSVC.
Dokumentacja branżowa
Istnieje obszerna dokumentacja dotycząca tych implementacji języka i platformy technologii AddressSanitizer.
Ten przełomowy artykuł na temat AddressSanitizera (external) opisuje implementację.
Zobacz też
- Rozwiązywanie znanych problemów z programemSanitizer
- Dokumentacja języka i kompilacji narzędzia AddressSanitizer
- AddressSanitizer runtime reference (Dokumentacja środowiska uruchomieniowego AddressSanitizer)
- Bajty w tle addressSanitizer
- AddressSanitizer — chmura lub testowanie rozproszone
- Integracja debugera AddressSanitizer
- Przykłady błędów addressSanitizer