Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Verwendung von Sanitizern

Was sind Sanitizer?

Sanitizer sind statische Instrumentierungswerkzeuge, die dabei helfen, Bugs zu finden, die traditionelle Debugger normalerweise nicht aufspüren können. Dies ist besonders nützlich in Kombination mit Unit-Tests bei der Continuous Integration.

Sanitizer können unter Windows, macOS und Linux mit den Compilern Clang (LLVM), GCC oder Visual Studio verwendet werden. Bestimmte Plattformen können auch ihre eigenen Sanitizer zur Verfügung stellen. In Situationen, in denen ein einziger Sanitizer von mehreren verschiedenen Compilern bereitgestellt wird, sollten Sie daran denken, dass sich ihre Ausgabe und ihr Verhalten leicht unterscheiden werden.

Verwendung von Sanitizern in Godot

Sanitizer erfordern eine Neukompilierung der Binärdatei. Das bedeutet, dass Sie keine offiziellen Godot-Binärdateien verwenden können, um Sanitizer auszuführen.

Wenn einer der Sanitizer beim Kompilieren aktiviert ist, bekommt die resultierende Binärdatei das Suffix .san an ihren Namen angehängt, um sie von einer Binärdatei ohne Sanitizer zu unterscheiden.

Dies hat Auswirkungen auf die Performance, da viele zusätzliche Laufzeitprüfungen durchgeführt werden müssen. Auch die Speichernutzung wird sich erhöhen. Es ist möglich, bestimmte Kombinationen von mehreren Sanitizern in einem einzigen Build zu aktivieren. Beachten Sie jedoch die Auswirkungen auf die Performance, wenn Sie mehrere Sanitizer gleichzeitig verwenden, da die resultierende Binärdatei übermäßig langsam sein kann.

Bestimmte Optionen können mit Hilfe von Umgebungsvariablen an Sanitizer übergeben werden, ohne dass die Binärdatei neu kompiliert werden muss.

Adress-Sanitizer (ASAN)

  • Verfügbar in Clang und GCC.

  • Unterstützte Plattformen: Linux, macOS, Windows (Visual Studio), Web

  • Clang ASAN-Dokumentation

Der Adress-Sanitizer ist im Allgemeinen der am häufigsten verwendete Sanitizer. Er kann Probleme wie Buffer Overruns und Out-of-Bounds-Zugriffe diagnostizieren. Wenn die Engine mit einer Meldung wie free(): invalid pointer abstürzt, ist dies typischerweise das Ergebnis eines Buffer Overruns. (Diese Meldung wird von der C-Runtime ausgegeben, nicht von Godot).

In bestimmten Situationen (z.B. beim Erkennen von nicht initialisierten Speicherlesevorgängen) reicht der Adress-Sanitizer nicht aus. Stattdessen sollte der Memory-Sanitizer (MSAN) verwendet werden.

Es ist auch möglich, Use-after-return-Situationen zu erkennen, indem man die Umgebungsvariable ASAN_OPTIONS=detect_stack_use_after_return=1 angibt, bevor man Godot ausführt (nicht beim Kompilieren). Dies erhöht den Laufzeit-Overhead des Adress-Sanitizers, daher sollten Sie dieses Feature nur aktivieren, wenn Sie es tatsächlich benötigen.

Um den Adress-Sanitizer in einem Godot-Build zu aktivieren, übergeben Sie beim Kompilieren die SCons-Option use_asan=yes. Die Aktivierung von ASAN macht die resultierende Binärdatei im Allgemeinen etwa zweimal langsamer.

Warnung

Aufgrund einer Designentscheidung schließen sich die Adress-, Memory- und Thread-Sanitizer gegenseitig aus. Das bedeutet, dass Sie nur einen dieser Sanitizer in einer bestimmten Binärdatei verwenden können.

Leak-Sanitizer (LSAN)

Der Leak-Sanitizer kann Speicherleaks aufspüren, d. h. Situationen, in denen Speicher, der nicht mehr verwendet wird, vom laufenden Programm nie freigegeben wird. Dies kann möglicherweise zu Out-of-Memory-Situationen führen, wenn das Programm lange genug läuft. Da Godot auf dedizierten Servern über Monate oder sogar Jahre ohne Neustart laufen kann, ist es wichtig, Speicherleaks zu beheben, wenn sie auftreten.

Um den Leak-Sanitizer in einem Godot-Build zu aktivieren, übergeben Sie beim Kompilieren die SCons-Option use_lsan=yes. Die Aktivierung von LSAN hat nur einen geringen Performance-Overhead, aber das Programm wird viel langsamer beendet, da die Leak-Erkennung beim Beenden des Programms erfolgt.

Memory-Sanitizer (MSAN)

Der Memory-Sanitizer ergänzt den Adress-Sanitizer (ASAN). Im Gegensatz zum Adress-Sanitizer kann der Memory-Sanitizer nicht-initialisierte Memory Reads erkennen.

Um den Memory-Sanitizer in einem Godot-Build zu aktivieren, übergeben Sie beim Kompilieren die SCons-Option use_msan=yes. Die Aktivierung von MSAN macht die resultierende Binärdatei im Allgemeinen etwa 3x langsamer.

Warnung

Aufgrund einer Designentscheidung schließen sich die Adress-, Memory- und Thread-Sanitizer gegenseitig aus. Das bedeutet, dass Sie nur einen dieser Sanitizer in einer bestimmten Binärdatei verwenden können.

Thread-Sanitizer (TSAN)

Der Thread-Sanitizer wird verwendet, um Race Conditions im Zusammenhang mit Multithreading aufzuspüren. Eine Race Condition liegt vor, wenn mehrere Threads versuchen, dieselben Daten zur gleichen Zeit zu ändern. Da die Threads beim Scheduling vom Betriebssystem in beliebiger Reihenfolge angeordnet werden können, führt dies zu fehlerhaftem Verhalten, das aber nur gelegentlich auftritt (und daher schwer zu tracken sein kann). Um eine Race Condition zu verhindern, müssen Sie ein Lock hinzufügen, um sicherzustellen, dass nur ein Thread zu einem bestimmten Zeitpunkt auf die gemeinsamen Daten zugreifen kann.

Um den Thread-Sanitizer in einem Godot-Build zu aktivieren, übergeben Sie beim Kompilieren die SCons-Option use_tsan=yes. Durch die Aktivierung von TSAN wird die resultierende Binärdatei im Allgemeinen um das 10-fache langsamer, während sich die Speichernutzung um das 8-fache erhöht.

Warnung

Aufgrund einer Designentscheidung schließen sich die Adress-, Memory- und Thread-Sanitizer gegenseitig aus. Das bedeutet, dass Sie nur einen dieser Sanitizer in einer bestimmten Binärdatei verwenden können.

Sanitizer für undefiniertes Verhalten (UBSAN)

Der Sanitizer für undefiniertes Verhalten wird verwendet, um Situationen aufzuspüren, in denen das Programm ein zufälliges und unvorhersehbares Verhalten zeigt. Dies ist auf C/C++-Code zurückzuführen, der zwar vom Compiler akzeptiert wird, aber nicht korrekt ist. Auch das Kompilieren mit einem anderen Satz von Optimierungen kann die beobachteten Ergebnisse von undefiniertem Verhalten verändern.

Um den Sanitizer für undefiniertes Verhalten in einem Godot-Build zu aktivieren, übergeben Sie die SCons-Option use_ubsan=yes beim Kompilieren. Die Aktivierung von UBSAN hat nur einen geringen Performance-Overhead.

Plattformspezifische Sanitizer

Web

Bei der Kompilierung für das Web gibt es 2 zusätzliche Sanitizer SCons-Optionen:

  • use_assertions=yes aktiviert Emscripten-Assertions zur Laufzeit, die verschiedene Probleme abfangen können.

  • use_safe_heap=yes aktiviert Emscriptens SAFE_HEAP-Sanitizer. Er bietet eine ähnliche Funktionalität wie ASAN, aber es konzentriert sich auf Probleme, die spezifisch für WebAssembly sind. Es ist nicht garantiert, dass SAFE_HEAP mit ASAN und UBSAN in der gleichen Binärdatei kompatibel ist, so dass Sie es möglicherweise separat bauen müssen.