AddressSanitizer(ASan)是Clang/GCC提供的编译期插桩内存检测工具,可快速发现缓冲区溢出、use-after-free等错误,需编译链接均加-fsanitize=address、禁用高优化并加-g,运行时报错含详细堆栈与内存信息。

AddressSanitizer(ASan)是 Clang 和 GCC 提供的内存错误检测工具,能快速发现堆栈缓冲区溢出、use-after-free、double-free、内存泄漏(需额外开启)等常见问题。它不是运行时库,而是编译期插桩 + 运行时检测,开销约 2×,但远比 Valgrind 快。
编译时启用 ASan
关键是在编译和链接阶段都加上 -fsanitize=address,并建议禁用优化(或至少不用 -O2 及以上),否则可能漏报或误报:
- Clang:
clang++ -fsanitize=address -g -O1 main.cpp -o main - GCC(≥4.8):
g++ -fsanitize=address -g -O1 main.cpp -o main - 务必加 -g,否则报错时看不到源码行号
- 避免 -O2/-O3:优化可能把检测逻辑优化掉,或导致栈变量生命周期判断不准
运行时行为与典型报错
程序运行后一旦触发非法内存访问,ASan 会立即终止进程,并打印带堆栈、内存布局、访问地址、对象起源等信息的详细报告:
- 例如越界写:
ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000001c - 例如释放后使用:
ERROR: AddressSanitizer: use-after-free on address 0x602000000030 - 报告中会标出分配/释放位置(
allocated by thread T0 here:)、访问位置、以及附近内存快照 - 默认不检测内存泄漏;如需开启,运行时加环境变量:
ASAN_OPTIONS=detect_leaks=1 ./main
常见配置与调试技巧
通过环境变量可微调 ASan 行为,适合不同场景:
立即学习“C++免费学习笔记(深入)”;
-
ASAN_OPTIONS=abort_on_error=1:出错直接 abort,方便用 gdb 调试(gdb ./main→run→ 崩溃后bt) -
ASAN_OPTIONS=disable_coredump=0:允许生成 core dump,便于事后分析 -
ASAN_OPTIONS=allocator_may_return_null=1:让 new 失败时返回 nullptr 而非抛异常(兼容旧代码) - 若项目含内联汇编或自定义内存管理(如对象池),可能触发误报,可用
__asan_poison_memory_region()/__asan_unpoison_memory_region()手动标记
CMake 项目中集成 ASan
在 CMakeLists.txt 中添加条件编译支持,避免每次手动改命令:
- 启用方式:
cmake -DCMAKE_CXX_FLAGS="-fsanitize=address -g -O1" -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address" .. - 或在 CMakeLists.txt 内加:
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang|GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g -O1") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") endif() - 注意:CMake 的
add_compile_options不影响链接器标志,必须单独设CMAKE_EXE_LINKER_FLAGS









