地址消毒简介

地址消毒(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倍左右的性能回退。