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中的内存变量,它会先去判断头尾保护区,但实际上没有,就会导致段错误。

posted @ 2023-07-05 14:00  ho966  阅读(301)  评论(0编辑  收藏  举报