LLVM/Clang的sanitizer:ASan/UBSan/TSan/MSan
请介绍 LLVM sanitizer 系列工具(AddressSanitizer/UndefinedBehaviorSanitizer/ThreadSanitizer/MemorySanitizer)的用途、编译选项、运行时行为及在 CI 中的应用。
回答
古法程序员
Sanitizer 系列:编译期插桩 + 运行时检测。
| Sanitizer | 选项 | 检测问题 | 性能开销 |
|---|---|---|---|
| ASan | -fsanitize=address | 堆越界、栈越界、use-after-free、double-free | ~2x |
| UBSan | -fsanitize=undefined | 整型溢出、空指针解引用、除零、移位越界 | ~1.2x |
| TSan | -fsanitize=thread | 数据竞争(race condition) | ~5x |
| MSan | -fsanitize=memory | 未初始化内存读取 | ~3x |
| LSan | -fsanitize=leak | 内存泄漏(常与 ASan 一起) | 极低 |
使用示例:
# ASan + UBSan
g++ -g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer main.cpp -o main
./main # 出现错误时打印详细信息并退出
ASan 输出关键信息:
- 错误类型(如 HEAP-USE-AFTER-FREE)
- 调用栈(首次分配、释放、当前访问的位置)
- 影子内存映射
UBSan 检查子项:-fsanitize=undefined 包含:
shift-base/shift-exponentsigned-integer-overflowvla-bound/null/returnpointer-overflow(C++20)
CI 最佳实践:
- 在 Debug 测试中开启 ASan+UBSan。
- 多线程测试开启 TSan。
- 由于性能开销,不对 Release 构建开启。