In diesem Dokument erfahren Sie, wie Sie spezielle Debugging-Tools bei der Verwendung von AGDE aktivieren. Diese Tools können bei schwer zu diagnostizierenden Speicherbeschädigungen und Überschreibfehlern helfen.
HWAddress Sanitizer und Address Sanitizer
HWAddress Sanitizer (HWASan) und AddressSanitizer (ASan) sind Tools zum Beheben von Speicherbeschädigungen, die bei der Behebung von Speicherbeschädigungen und Überschreibungsfehlern helfen, z. B.:
- Stack-Pufferüberläufe und -Unterläufe
- Heap-Pufferüberläufe und ‑Unterläufe
- Verwendung des Stacks außerhalb seines Gültigkeitsbereichs
- Fehler vom Typ „Double free“ und „Wild free“
- Stacknutzung nach Rückgabe (nur HWASan)
Wir empfehlen, HWASan oder ASan nur zu aktivieren, wenn Sie ein Problem beheben oder automatisierte Tests durchführen. Diese Tools sind zwar leistungsstark, ihre Verwendung führt jedoch zu einer Strafzahlung.
Laufzeitverhalten
Wenn diese Option aktiviert ist, prüfen sowohl HWASan als auch ASan automatisch auf Speicherbeschädigungen in Ihrer App.
Wenn ein Speicherfehler erkannt wird, stürzt die App mit dem Fehler SIGBART
(Signalabbruch) ab und druckt eine detaillierte Meldung in logcat aus. Eine Kopie der Nachricht wird auch in eine Datei unter /data/tombstones
geschrieben.
Die Fehlermeldung sieht in etwa so aus:
ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
#0 0x7b24d90a08 (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
#1 0x7b8f1e4ccc (/apex/com.android.art/lib64/libart.so+0x198ccc)
#2 0x7b8f1db364 (/apex/com.android.art/lib64/libart.so+0x18f364)
#3 0x7b8f2ad8d4 (/apex/com.android.art/lib64/libart.so+0x2618d4)
0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
#0 0x7b92a322bc (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
#1 0x7b24d909e0 (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
#2 0x7b8f1e4ccc (/apex/com.android.art/lib64/libart.so+0x198ccc)
Voraussetzungen
HWASan-Anforderungen
So verwenden Sie HWASan:
- Sie müssen AGDE 24.1.99 oder höher verwenden.
- Die App muss mit NDK 26 oder höher erstellt werden.
- Die App muss mit dem Ziel-SDK 34 oder höher erstellt werden.
- Das Ziel muss ein
arm64-v8a
-Gerät mit Android 14 (API-Level 34) oder höher sein.
Gemeinsam genutzte C++-Standardbibliothek in Ihrem Projekt verwenden
Aufgrund eines bekannten Problems ist ASan bei Verwendung von libc++_static
nicht mit der C++-Ausnahmebehandlung kompatibel. Bei der Verwendung von libc++_shared
tritt dieses Problem nicht auf.
HWASan hat eine eigene Implementierung der Operatoren new
und delete
, die nicht verwendet werden kann, wenn die Standardbibliothek statisch mit dem Projekt verknüpft ist.
Informationen zum Ändern dieser Einstellung finden Sie im Abschnitt C++-Standardbibliothek verknüpfen dieses Dokuments.
Generierung von Frame Pointer aktivieren
HWASan und ASan verwenden einen schnellen Frame-Pointer-basierten Unwinder, um Informationen zum Stack-Trace für Speicherallokations- und -delokationsereignisse zu generieren. Das bedeutet, dass Sie die Generierung von Framepointern in den C++-Compilereinstellungen aktivieren müssen, um diese Funktionen zu verwenden. Sie müssen also die Optimierung des Auslassens von Framepointern deaktivieren.
Informationen zum Ändern dieser Einstellung finden Sie in diesem Dokument im Abschnitt Generierung von Frame Pointer aktivieren.
Visual Studio-Projekt für die Verwendung von HWASan oder ASan konfigurieren
HWASan oder ASan aktivieren
Wenn Sie HWASan oder ASan aktivieren möchten, rufen Sie auf der Seite Property-Seiten für Ihr Projekt die Option Konfigurationseigenschaften > Allgemein auf.
Abbildung 1: Die Option Properties (Eigenschaften) des Projekts im Visual Studio-Fenster „Solution Explorer“
Abbildung 2: Die Einstellung Address Sanitizer (ASan) in den allgemeinen Projekteigenschaften.
Wenn Sie HWASan für Ihr Projekt aktivieren möchten, ändern Sie die Einstellung Address Sanitizer (ASan) in Hardware ASan Enabled (fsanitize=hwaddress).
Wenn Sie ASan für Ihr Projekt aktivieren möchten, ändern Sie die Einstellung Address Sanitizer (ASan) in ASan Enabled (fsanitize=address).
Generierung von Frame Pointer aktivieren
Die Generierung von Frame Pointern wird durch die C/C++-Compilereinstellung Omit Frame Pointer gesteuert. Sie finden sie auf den Property-Seiten Ihres Projekts unter Konfigurationseigenschaften > C/C++ > Optimierung.
Abbildung 3: Speicherort der Einstellung Omit Frame Pointer
Wenn Sie HWASan oder ASan verwenden, setzen Sie die Einstellung Omit Frame Pointer auf No (-fno-omit-frame-pointer).
C++-Standardbibliothek im Modus „Gemeinsam genutzte Bibliothek“ verknüpfen
Die Einstellung für den Linker-Modus der C++-Standardbibliothek finden Sie auf den Property-Seiten Ihres Projekts unter Konfigurationseigenschaften > Allgemein im Abschnitt Projektstandardwerte.
Abbildung 4: Speicherort der Einstellung für den Linker-Modus der C++-Standardbibliothek
Wenn Sie HWASan oder ASan verwenden, legen Sie für Use of STL (STL verwenden) die Option Use C++ Standard Libraries (.so) (C++-Standardbibliotheken (.so) verwenden) fest. Mit diesem Wert wird die C++-Standardbibliothek als freigegebene Bibliothek mit Ihrem Projekt verknüpft. Dies ist erforderlich, damit HWASan und ASan ordnungsgemäß funktionieren.
Build-Konfiguration für die Verwendung von Address Sanitizer erstellen
Wenn Sie HWASan oder ASan vorübergehend verwenden möchten, sollten Sie nicht nur zu diesem Zweck eine neue Buildkonfiguration erstellen. Das kann der Fall sein, wenn Ihr Projekt klein ist, Sie die Funktion ausprobieren oder auf ein Problem reagieren, das Sie während des Tests feststellen.
Wenn Sie es jedoch für nützlich halten und regelmäßig verwenden möchten, können Sie eine neue Build-Konfiguration für HWASan oder ASan erstellen, wie im Teapot-Beispiel gezeigt. Das kann beispielsweise der Fall sein, wenn Sie Address Sanitizer regelmäßig als Teil Ihrer Unit-Tests oder während nächtlicher Smoke-Tests Ihres Spiels ausführen.
Das Erstellen einer separaten Build-Konfiguration kann besonders nützlich sein, wenn Sie ein großes Projekt mit einer großen Anzahl verschiedener Drittanbieterbibliotheken haben, die Sie normalerweise statisch mit der C++-Standardbibliothek verknüpfen. Spezielle Build-Konfigurationen können dazu beitragen, dass Ihre Projekteinstellungen immer korrekt sind.
Wenn Sie eine Buildkonfiguration erstellen möchten, klicken Sie auf den Tab Eigenschaften Ihres Projekts und dann auf die Schaltfläche Konfigurationsmanager…. Öffnen Sie dann das Drop-down-Menü Aktive Lösungskonfiguration. Wählen Sie dann
HWASan mit benutzerdefinierten Speicherallokatoren verwenden
HWASan fängt automatisch den über malloc
(oder new
) zugewiesenen Arbeitsspeicher ab, damit Tags in Zeiger eingefügt und auf Tag-Abweichungen geprüft werden können.
Bei Verwendung eines benutzerdefinierten Speicherallokators kann HWASan Ihre benutzerdefinierten Speicherallokationsmethoden jedoch nicht automatisch abfangen. Wenn Sie HWASan mit Ihrem benutzerdefinierten Speicherallokator verwenden möchten, müssen Sie Ihren Speicherallokator so instrumentieren, dass er HWASan explizit aufruft. Das ist mit nur wenigen Codezeilen möglich.
Voraussetzungen
Die HWASan-Methoden, die du aufrufen musst, sind in diesem Header definiert:
#include "sanitizer/hwasan_interface.h"
Speicherzuweisung erfassen
Weisen Sie Objekte mit einer Blockgranularität und ‑ausrichtung von 16 Byte zu. Wenn Sie beispielsweise einen Pool-Allocator haben, der Objekte mit einer festen Größe von 24 Byte bereitstellt, runden Sie Ihre Zuweisungen auf 32 Byte auf und binden Sie sie auf 16 Byte.
Erstellen Sie ein 8‑Bit-Tag. Die Werte 0–16 dürfen nicht verwendet werden, da sie für die interne Verwendung reserviert sind.
Aktivieren Sie HWASan, um mit diesem Tag die Speicherregion zu erfassen:
__hwasan_tag_memory((void*) address, tag, size);
Führen Sie das Tag in die oberen 8 Bit Ihres Cursors ein:
address = __hwasan_tag_pointer((void*) address, tag);
Methode zur Speicherfreigabe instrumentieren
Setzen Sie das Tag für den Speicherbereich zurück, damit weitere Zugriffe über die vorhandenen getaggten Zeiger fehlschlagen:
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), 0, size);
Mit einem vorab zugewiesenen Objektpool arbeiten
Wenn Ihr Speicherallokator Objekte in einem Pool vorab zuweist und Objekte zurück in den Pool gibt, anstatt sie tatsächlich freizugeben, kann Ihre Methode zur Speicherfreigabe das Tag für den Speicher und den Zeiger direkt mit einem neuen Wert überschreiben:
```
__hwasan_tag_memory(__hwasan_tag_pointer(ptr, 0), tag, size);
ptr = __hwasan_tag_pointer((void*)ptr, tag);
```
Bei dieser Methode müssen Ihre Zuweisungsmethoden keine Zeiger oder Speicherblöcke taggen, sondern die Zeiger und Speicherblöcke, wenn Sie die Objekte in Ihrem Pool vorab zuweisen. Im Beispiel für PoolAllocator wird dieser Stil verwendet.