Fehler: stack-use-after-return
Adressbereinigungsfehler: Verwendung des Stapelspeichers nach der Rückgabe
Für diese Überprüfung ist die Codegenerierung erforderlich, die von einer zusätzlichen Compileroption aktiviert wird, /fsanitize-address-use-after-return
und durch Festlegen der Umgebungsvariable ASAN_OPTIONS=detect_stack_use_after_return=1
.
Diese Prüfung kann Ihre Anwendung erheblich verlangsamen. Betrachten Sie die Clang-Zusammenfassung des Algorithmus, der die Verwendung nach der Rückgabe unterstützt, und die größeren Leistungskosten.
Wichtig
Wenn Sie eine Objektdatei mit der zusätzlichen Compileroption /fsanitize-address-use-after-return
erstellen, trifft der vom Compiler generierte Code eine Laufzeitentscheidung darüber, wie ein Stapelframe zugewiesen werden soll. Wenn die Umgebungsvariable ASAN_OPTIONS
nicht auf festgelegt detect_stack_use_after_return
ist, ist der Code immer noch langsamer als die Verwendung /fsanitize=address
selbst. Es ist langsamer, da es noch zusätzlichen Aufwand von einigen Stapelframes gibt, die Platz für Teile eines Frames mithilfe alloca()
von . Es ist am besten, diese Objektdateien zu löschen, wenn Sie die Verarbeitung von Verwendungsfehlern nach dem Zurückgeben abgeschlossen haben.
Beispiel – Einfaches C
// example1.cpp
// stack-use-after-return error
volatile char* x;
void foo() {
char stack_buffer[42];
x = &stack_buffer[13];
}
int main() {
foo();
*x = 42; // Boom!
return (*x == 42);
}
Führen Sie zum Erstellen und Testen dieses Beispiels die folgenden Befehle in einer Visual Studio 2019,16.9- oder höher-Entwickler-Eingabeaufforderung aus:
cl example1.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example1.exe
Resultierender Fehler - Einfaches C
Beispiel : C++ und Vorlagen
// example2.cpp
// stack-use-after-return error
#include <stdlib.h>
enum ReadOrWrite { Read = 0, Write = 1 };
struct S32 {
char x[32];
};
template<class T>
T* LeakStack() {
T t[100];
static volatile T* x;
x = &t[0];
return (T*)x;
}
template<class T>
void StackUseAfterReturn(int Idx, ReadOrWrite w) {
static T sink;
T* t = LeakStack<T>();
if (w)
t[100 + Idx] = T();
else
sink = t[100 + Idx];
}
int main(int argc, char* argv[]) {
if (argc != 2) return 1;
int kind = atoi(argv[1]);
switch (kind) {
case 1: StackUseAfterReturn<char>(0, Read); break;
case 2: StackUseAfterReturn<S32>(0, Write); break;
}
return 0;
}
Führen Sie zum Erstellen und Testen dieses Beispiels die folgenden Befehle in einer Visual Studio 2019,16.9- oder höher-Entwickler-Eingabeaufforderung aus:
cl example2.cpp /fsanitize=address /fsanitize-address-use-after-return /Zi /Od
set ASAN_OPTIONS=detect_stack_use_after_return=1
devenv /debugexe example2.exe 1
ASAN ist eine Form der dynamischen Analyse, was bedeutet, dass nur fehlerhaften Code erkannt werden kann, der tatsächlich ausgeführt wird. Ein Optimierer kann bestimmen, dass der Wert der t[100 + Idx]
Zuordnung verwendet oder sink
nie verwendet wird. Daher erfordert dieses Beispiel die /Od
Kennzeichnung.
Resultierender Fehler – C++ und Vorlagen
Siehe auch
AddressSanitizer -Übersicht
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