asan
参考资料:https://blog.csdn.net/weixin_45396052/article/details/119136109
简介
address sanitizier(地址消毒剂),简称asan, 是一款内存检测工具,可用于检测一下错误:
1、 堆内存、栈内存和全局变量的越界(-fsanitize=address)
2、 已释放内存(野指针)的使用(-fsanitize=address)
3、 内存泄漏(-fsanitize=leak)
4、 作用域外的使用(clang flag -fsanitize-address-use-after-scope)
5、 返回值使用(runtime flag ASAN_OPTIONS=detect_stack_use_after_return=1)
GCC版本要求:
GCC4.8及其以上,若要查内存泄漏(LeakSanitizer),需GCC>=4.9
ARM版本GCC>=4.9
编译选项:
-fsanitize=address 内存错误检测
-fno-omit-frame-pointer 让gcc产生stack frame
-fsanitize=leak 内存泄漏检测,gcc>=4.9
-fsanitize=bounds 数组索引越界
设置log文件路径:
export ASAN_OPTIONS=”/home/1.log”
原理
asan工具包括两部分:编译时插桩模块和运行时库
编译时插桩模块:
加了 ASAN 相关的编译选项后,代码中的内存访问操作都会被编译器修改,主要有如下两类操作
1、 会给栈变量和全局变量添加头和尾保护区,
2、 会对内存变量的访问插入合法性检测代码
运行时库:
运行时库( libasan.so.x )会接管 malloc 和 free 之类的内存操作函数
1、 堆空间申请的内存添加头尾保护区,即red-zone
2、 维护影子区的状态信息,虚拟内存一个指针长度(64位16bytes,32位8字节)和影子区一个byte对应,该字节保存虚拟内存一个指针长度的状态,例如不可访问、前多少字 节可访问等
3、 在访问内存变量前,根据影子区的状态判断是否合法,不合法就输出报告
注意:
asan是希望进程所有库都编译时插桩,如果动态库a编译选项加了asan选项,依赖a的库b没有添加asan编译选项,那当b调用a中的接口时,a库使用b中的内存变量,它会先去判断头尾保护区,但实际上没有,就会导致段错误。