使用 Sanitizer

什么是 Sanitizer?

Sanitizer 是一种静态检测工具,能够帮助找出传统调试器通常无法捕捉的问题。非常适合在持续集成中与 单元测试 结合使用。

在 Windows、macOS、Linux 平台使用 Clang(LLVM)、GCC、Visual Studio 编译器时能够使用 Sanitizer。部分平台可能也可以使用其独有的 Sanitizer。多种不同的编译器都提供相同的某种 Sanitizer 时,请记住它们的输出和行为有可能略有不同。

在 Godot 中使用 Sanitizer

Sanitizer 要求重新编译二进制文件。这意味着你无法使用官方 Godot 二进制文件来运行 Sanitizer。

When compiling with any of the sanitizers enabled, the resulting binary will have the .san suffix added to its name to distinguish it from a binary without sanitizers.

There is a performance impact as many additional runtime checks need to be performed. Memory utilization will also increase. It is possible to enable certain combinations of multiple sanitizers in a single build. Beware of the performance impact when using multiple sanitizers at once though, as the resulting binary may be excessively slow.

Certain options can be passed to sanitizers without having to recompile the binary using environment variables.

地址 Sanitizer(ASAN)

  • Clang 和 GCC 中可用。

  • 支持的平台:Linux、macOS、Windows(Visual Studio)、Web

  • Clang ASAN 文档

The address sanitizer is generally the most frequently used sanitizer. It can diagnose issues such as buffer overruns and out-of-bounds access. If the engine crashes with a message such as free(): invalid pointer, this is typically the result of a buffer overrun. (This message is printed by the C runtime, not Godot.)

In certain situations (such as detecting uninitialized memory reads), the address sanitizer doesn’t suffice. The 内存 Sanitizer(MSAN) should be used instead.

It is also possible to detect use-after-return situations by specifying the ASAN_OPTIONS=detect_stack_use_after_return=1 environment variable before running Godot (not when compiling it). This increases the address sanitizer’s runtime overhead, so only enable this feature when you actually need it.

To enable the address sanitizer in a Godot build, pass the use_asan=yes SCons option when compiling. Enabling ASAN generally makes the resulting binary about 2× slower.

警告

Due to a design decision, the address, memory and thread sanitizers are mutually exclusive. This means you can only use one of those sanitizers in a given binary.

泄漏 Sanitizer(LSAN)

The leak sanitizer can detect memory leaks, which are situations where memory that is no longer in use is never freed by the running program. This can potentially lead to out-of-memory situations if the program runs for long enough. Since Godot may run on dedicated servers for months or even years without a restart, it’s important to fix memory leaks when they occur.

To enable the leak sanitizer in a Godot build, pass the use_lsan=yes SCons option when compiling. Enabling LSAN only has a small performance overhead, but the program will be much slower to exit as leak detection occurs when the program exits.

内存 Sanitizer(MSAN)

The memory sanitizer complements the 地址 Sanitizer(ASAN). Unlike the address sanitizer, the memory sanitizer can detect uninitialized memory reads.

To enable the memory sanitizer in a Godot build, pass the use_msan=yes SCons option when compiling. Enabling MSAN generally makes the resulting binary about 3× slower.

警告

Due to a design decision, the address, memory and thread sanitizers are mutually exclusive. This means you can only use one of those sanitizers in a given binary.

线程 Sanitizer(TSAN)

The thread sanitizer is used to track down race conditions related to multithreading. A race condition is when multiple threads try to modify the same data at the same time. Since thread scheduling can be ordered in any fashion by the operating system, this leads to incorrect behavior that only occurs occasionally (and can be difficult to track as a result). To prevent a race condition, you need to add a lock to ensure only one thread can access the shared data at a given time.

To enable the thread sanitizer in a Godot build, pass the use_tsan=yes SCons option when compiling. Enabling TSAN generally makes the resulting binary 10× slower, while also multiplying memory usage by an approximately 8× factor.

警告

Due to a design decision, the address, memory and thread sanitizers are mutually exclusive. This means you can only use one of those sanitizers in a given binary.

未定义行为 Sanitizer(UBSAN)

The undefined behavior sanitizer is used to track down situations where the program exhibits random and unpredictable behavior. This is due to C/C++ code that is accepted by the compiler, but is not correct. Compiling with a different set of optimizations can also change the observed results of undefined behavior.

To enable the undefined behavior sanitizer in a Godot build, pass the use_ubsan=yes SCons option when compiling. Enabling UBSAN only has a small performance overhead.

平台相关 Sanitizer

Web

When compiling for the Web, there are 2 additional sanitizer SCons options available:

  • use_assertions=yes enables runtime Emscripten assertions, which can catch various issues.

  • use_safe_heap=yes enables Emscripten’s SAFE_HEAP sanitizer. It provides similar functionality to ASAN, but it focuses on issues that are specific to WebAssembly. SAFE_HEAP is not guaranteed to be compatible with ASAN and UBSAN in the same binary, so you may have to build it separately.