地址消毒(AddressSanitizer)是一个内存错误检测工具,通常由一个编译器插桩模块和一个运行时库组成,能够快速地检测常见的内存错误。最早是Google的论文《AddressSanitizer: A Fast Address Sanity Checker》介绍的一种新的内存检测方法,目前主流编译器中都支持了地址消毒。地址消毒的详细介绍可以参考llvm的官方文档。在使用毕昇编译器时加上-fsanitize=address选项,AddressSanitizer 运行时库即可以链接到最终的可执行文件,可以检测几种常见的错误类型,见下表:
错误类型 |
错误描述 |
---|---|
use-after-free |
访问堆上已被释放的内存 |
out-of-bounds accesses to heap, stack and globals |
对堆、堆栈和全局变量的越界访问 |
use-after-return |
访问栈上已经释放的内存 |
use-after-scope |
栈对象使用超过定义范围 |
double-free, invalid free |
重复释放同一内存或者无效释放内存区域 |
memory leaks |
内存泄漏 |
initialization order checking |
初始化顺序检查 |
通常情况下使用-fsanitize=address编译和链接程序即可使能AddressSanitizer。当链接共享库时,AddressSanitizer运行时不会被链接,所以-Wl,-z,defs可能会导致链接错误。添加-fno-omit-frame-pointer以禁用栈帧指针可以获取更好的调用栈。一般情况下使能地址消毒会造成2倍左右的性能回退。