sanitizers

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Sanitizers

Sanitizer工具集

Purpose

用途

Guide agents through choosing, enabling, and interpreting compiler runtime sanitizers for finding memory errors, undefined behaviour, data races, and memory leaks.
指导开发者选择、启用编译器运行时Sanitizer工具,并解读其检测结果,以发现内存错误、未定义行为、数据竞争及内存泄漏问题。

Triggers

触发场景

  • "My program has a memory error — which sanitizer do I use?"
  • "How do I enable ASan?"
  • "How do I interpret an ASan/UBSan/TSan report?"
  • "ASan says heap-buffer-overflow — what does that mean?"
  • "How do I suppress false positives in sanitizers?"
  • "Can I use sanitizers in CI?"
  • “我的程序出现内存错误,应该使用哪款Sanitizer?”
  • “如何启用ASan?”
  • “如何解读ASan/UBSan/TSan的检测报告?”
  • “ASan提示heap-buffer-overflow,这是什么意思?”
  • “如何抑制Sanitizer的误报?”
  • “能否在CI中使用Sanitizer?”

Workflow

操作流程

1. Decision tree: which sanitizer?

1. 选型决策树:选择合适的Sanitizer

Bug class?
├── Memory OOB, use-after-free, double-free → AddressSanitizer (ASan)
├── Stack OOB, global OOB → ASan (all three covered)
├── Uninitialised reads → MemorySanitizer (MSan, Clang only, requires all-clang build)
├── Undefined behaviour (int overflow, null deref, bad cast) → UBSan
├── Data races (multi-thread) → ThreadSanitizer (TSan)
├── Memory leaks only → LeakSanitizer (LSan, standalone or via ASan)
└── Multiple classes → ASan + UBSan (common combo); cannot combine with TSan or MSan
Bug类别?
├── 内存越界、释放后使用、重复释放 → AddressSanitizer (ASan)
├── 栈越界、全局变量越界 → ASan(可覆盖这三类问题)
├── 未初始化内存读取 → MemorySanitizer (MSan,仅支持Clang,需全Clang编译构建)
├── 未定义行为(整数溢出、空指针解引用、错误类型转换) → UBSan
├── 数据竞争(多线程场景) → ThreadSanitizer (TSan)
├── 仅检测内存泄漏 → LeakSanitizer (LSan,可独立使用或通过ASan启用)
└── 多类问题并存 → ASan + UBSan(常用组合);不可与TSan或MSan同时使用

2. AddressSanitizer (ASan)

2. AddressSanitizer (ASan)

bash
undefined
bash
undefined

GCC or Clang

GCC 或 Clang

gcc -fsanitize=address -fno-omit-frame-pointer -g -O1 -o prog main.c
gcc -fsanitize=address -fno-omit-frame-pointer -g -O1 -o prog main.c

Or

或者

clang -fsanitize=address -fno-omit-frame-pointer -g -O1 -o prog main.c

Runtime options (via `ASAN_OPTIONS`):
```bash
ASAN_OPTIONS=detect_leaks=1:abort_on_error=1:log_path=/tmp/asan.log ./prog
ASAN_OPTIONS
key
Effect
detect_leaks=0/1
Enable LeakSanitizer (default 1 on Linux)
abort_on_error=1
Call
abort()
instead of
_exit()
(for core dumps)
log_path=path
Write report to file
symbolize=1
Symbolize addresses (needs
llvm-symbolizer
in PATH)
fast_unwind_on_malloc=0
More accurate stacks (slower)
quarantine_size_mb=256
Delay reuse of freed memory
Interpreting ASan output:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000050
READ of size 4 at 0x602000000050 thread T0
    #0 0x401234 in foo /home/user/src/main.c:15
    #1 0x401567 in main /home/user/src/main.c:42

0x602000000050 is located 0 bytes after a 40-byte region
[0x602000000028, 0x602000000050) allocated at:
    #0 0x7f12345 in malloc ...
    #1 0x401234 in main /home/user/src/main.c:10
Reading: the top frame in
WRITE/READ
is the access site; the
allocated at
stack shows the allocation. The region is 40 bytes at
[start, end)
and the access is at
end
= one byte past the end (classic off-by-one).
clang -fsanitize=address -fno-omit-frame-pointer -g -O1 -o prog main.c

运行时选项(通过`ASAN_OPTIONS`设置):
```bash
ASAN_OPTIONS=detect_leaks=1:abort_on_error=1:log_path=/tmp/asan.log ./prog
ASAN_OPTIONS
配置项
作用
detect_leaks=0/1
启用LeakSanitizer(Linux下默认值为1)
abort_on_error=1
调用
abort()
而非
_exit()
(用于生成核心转储文件)
log_path=path
将检测报告写入指定文件
symbolize=1
对内存地址进行符号化(需将
llvm-symbolizer
加入PATH环境变量)
fast_unwind_on_malloc=0
生成更精确的调用栈(速度较慢)
quarantine_size_mb=256
延迟复用已释放的内存
解读ASan输出结果:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000050
READ of size 4 at 0x602000000050 thread T0
    #0 0x401234 in foo /home/user/src/main.c:15
    #1 0x401567 in main /home/user/src/main.c:42

0x602000000050 is located 0 bytes after a 40-byte region
[0x602000000028, 0x602000000050) allocated at:
    #0 0x7f12345 in malloc ...
    #1 0x401234 in main /home/user/src/main.c:10
解读:
WRITE/READ
部分的顶层栈帧是错误访问的位置;
allocated at
栈帧显示内存分配的位置。该内存区域大小为40字节,范围是
[start, end)
,而错误访问发生在
end
位置(典型的数组越界1字节问题)。

3. UndefinedBehaviorSanitizer (UBSan)

3. UndefinedBehaviorSanitizer (UBSan)

bash
gcc -fsanitize=undefined -g -O1 -o prog main.c
bash
gcc -fsanitize=undefined -g -O1 -o prog main.c

More complete: add specific checks

更全面的检测:添加特定检查项

gcc -fsanitize=undefined,integer -g -O1 -o prog main.c

Common UBSan checks:
- `signed-integer-overflow`
- `unsigned-integer-overflow` (not in `undefined` by default)
- `null` — null pointer dereference
- `bounds` — array index OOB (compile-time knowable bounds)
- `alignment` — misaligned pointer access
- `float-cast-overflow` — float-to-int conversion overflow
- `vptr` — C++ vtable type mismatch
- `shift-exponent` — shift >= bit width

```bash
gcc -fsanitize=undefined,integer -g -O1 -o prog main.c

常见UBSan检查项:
- `signed-integer-overflow`:有符号整数溢出
- `unsigned-integer-overflow`:无符号整数溢出(默认不包含在`undefined`检查集中)
- `null`:空指针解引用
- `bounds`:数组索引越界(编译期可确定边界的情况)
- `alignment`:指针访问未对齐
- `float-cast-overflow`:浮点转整数时溢出
- `vptr`:C++虚表类型不匹配
- `shift-exponent`:移位操作的指数大于等于数据位宽

```bash

Enable everything including integer overflow

启用所有检查项,包括整数溢出

gcc -fsanitize=undefined
-fsanitize=signed-integer-overflow,unsigned-integer-overflow,float-cast-overflow
-fno-sanitize-recover=all \ # abort instead of continue -g -O1 -o prog main.c

`-fno-sanitize-recover=all`: makes UBSan abort on first error (important for CI).

**Interpreting UBSan output:**
src/main.c:15:12: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
undefined
gcc -fsanitize=undefined
-fsanitize=signed-integer-overflow,unsigned-integer-overflow,float-cast-overflow
-fno-sanitize-recover=all \ # 检测到错误即终止程序,而非继续执行 -g -O1 -o prog main.c

`-fno-sanitize-recover=all`:让UBSan在检测到第一个错误时就终止程序(在CI环境中非常重要)。

**解读UBSan输出结果:**
src/main.c:15:12: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
undefined

4. ThreadSanitizer (TSan)

4. ThreadSanitizer (TSan)

bash
undefined
bash
undefined

Clang or GCC (GCC ≥ 4.8)

Clang 或 GCC(GCC 版本≥4.8)

clang -fsanitize=thread -g -O1 -o prog main.c
clang -fsanitize=thread -g -O1 -o prog main.c

TSan is incompatible with ASan and MSan

TSan 与 ASan、MSan 不兼容


**Interpreting TSan output:**
WARNING: ThreadSanitizer: data race (pid=12345) Write of size 4 at 0x7f... by thread T2: #0 increment /home/user/src/counter.c:8 Previous read of size 4 at 0x7f... by thread T1: #0 read_counter /home/user/src/counter.c:3
undefined

**解读TSan输出结果:**
WARNING: ThreadSanitizer: data race (pid=12345) Write of size 4 at 0x7f... by thread T2: #0 increment /home/user/src/counter.c:8 Previous read of size 4 at 0x7f... by thread T1: #0 read_counter /home/user/src/counter.c:3
undefined

5. MemorySanitizer (MSan)

5. MemorySanitizer (MSan)

MSan detects reads of uninitialised memory. Clang only. Requires all-instrumented build (no mixing of MSan and non-MSan objects).
bash
clang -fsanitize=memory -fno-omit-frame-pointer -g -O1 -o prog main.c
MSan用于检测未初始化内存的读取操作。仅支持Clang,需全 instrumentation 构建(不能混合使用MSan编译和非MSan编译的目标文件)。
bash
clang -fsanitize=memory -fno-omit-frame-pointer -g -O1 -o prog main.c

With origin tracking (slower but shows where uninit value came from)

启用来源追踪(速度较慢,但可显示未初始化值的来源)

clang -fsanitize=memory -fsanitize-memory-track-origins=2 -g -O1 -o prog main.c

System libraries must be rebuilt with MSan or substituted with MSan-instrumented wrappers. Use `msan-libs` toolchain from LLVM.
clang -fsanitize=memory -fsanitize-memory-track-origins=2 -g -O1 -o prog main.c

系统库必须使用MSan重新编译,或替换为经过MSan instrumentation的包装库。可使用LLVM提供的`msan-libs`工具链。

6. ASan + UBSan combined

6. ASan + UBSan 组合使用

bash
gcc -fsanitize=address,undefined -fno-sanitize-recover=all \
    -fno-omit-frame-pointer -g -O1 -o prog main.c
Do not combine with TSan or MSan.
bash
gcc -fsanitize=address,undefined -fno-sanitize-recover=all \
    -fno-omit-frame-pointer -g -O1 -o prog main.c
不可与TSan或MSan同时使用。

7. Suppressions

7. 抑制误报

bash
undefined
bash
undefined

ASan suppression file

ASan 抑制文件

cat > asan.supp << 'EOF'
cat > asan.supp << 'EOF'

Suppress leaks from OpenSSL init

抑制OpenSSL初始化时的内存泄漏误报

leak:CRYPTO_malloc EOF
LSAN_OPTIONS=suppressions=asan.supp ./prog
leak:CRYPTO_malloc EOF
LSAN_OPTIONS=suppressions=asan.supp ./prog

UBSan suppression

UBSan 抑制文件

cat > ubsan.supp << 'EOF' signed-integer-overflow:third_party/fast_math.c EOF UBSAN_OPTIONS=suppressions=ubsan.supp:print_stacktrace=1 ./prog
undefined
cat > ubsan.supp << 'EOF' signed-integer-overflow:third_party/fast_math.c EOF UBSAN_OPTIONS=suppressions=ubsan.supp:print_stacktrace=1 ./prog
undefined

8. CMake integration

8. CMake 集成

cmake
option(SANITIZE "Enable sanitizers" OFF)
if(SANITIZE)
    set(san_flags -fsanitize=address,undefined -fno-sanitize-recover=all
                  -fno-omit-frame-pointer -g -O1)
    add_compile_options(${san_flags})
    add_link_options(${san_flags})
endif()
cmake
option(SANITIZE "Enable sanitizers" OFF)
if(SANITIZE)
    set(san_flags -fsanitize=address,undefined -fno-sanitize-recover=all
                  -fno-omit-frame-pointer -g -O1)
    add_compile_options(${san_flags})
    add_link_options(${san_flags})
endif()

9. CI integration

9. CI 集成

yaml
undefined
yaml
undefined

GitHub Actions example

GitHub Actions 示例

  • name: Build with ASan+UBSan run: | cmake -S . -B build -DSANITIZE=ON cmake --build build -j$(nproc)
  • name: Run tests under sanitizers run: | ASAN_OPTIONS=abort_on_error=1:detect_leaks=1
    UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1
    ctest --test-dir build -j$(nproc) --output-on-failure

For a quick flag reference, see [references/flags.md](references/flags.md).
For report interpretation examples, see [references/reports.md](references/reports.md).
  • name: Build with ASan+UBSan run: | cmake -S . -B build -DSANITIZE=ON cmake --build build -j$(nproc)
  • name: Run tests under sanitizers run: | ASAN_OPTIONS=abort_on_error=1:detect_leaks=1
    UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1
    ctest --test-dir build -j$(nproc) --output-on-failure

快速参考编译选项可查看 [references/flags.md](references/flags.md)。
检测报告解读示例可查看 [references/reports.md](references/reports.md)。

Related skills

相关技能

  • Use
    skills/profilers/valgrind
    for Memcheck when ASan is unavailable
  • Use
    skills/runtimes/fuzzing
    to auto-generate inputs that trigger sanitizer errors
  • Use
    skills/compilers/gcc
    or
    skills/compilers/clang
    for build flag context
  • 当ASan不可用时,使用
    skills/profilers/valgrind
    的Memcheck工具
  • 使用
    skills/runtimes/fuzzing
    自动生成可触发Sanitizer错误的测试输入
  • 如需编译选项相关上下文,可使用
    skills/compilers/gcc
    skills/compilers/clang
    技能