内存泄露检测工具-AddressSanitzer

0. 简介
2012 年,Google 发布了一篇论文:《AddressSanitizer: A Fast Address Sanity Checker》。介绍了一种新的内存检测方法,让上面的问题得到了很大的改进。截止到目前,AddressSanitizer 已经被广泛应用到了各种语言: C、C++、Objective-C、Java 等。以 Google 自己的 benchmark 为参考,开启 ASan 后,会使程序运行速度平均下降 2 倍左右,内存占用会增加 3 倍左右(和硬件有关)。这和其他工具动辄十几倍的消耗要好上不少。(如果要跑比较大的包,还是建议用AddressSanitzer的)。对于Address Sanitizer可以用来检测如下内存使用错误:

  • 内存释放后又被使用;
  • 内存重复释放;
  • 释放未申请的内存;
  • 使用栈内存作为函数返回值;
  • 使用了超出作用域的栈内存;
  • 内存越界访问;

1. AddressSanitzer是怎么做的
加了 ASAN 相关的编译选项后,代码中的每一次内存访问操作都会被编译器修改 为如下方式:

编译后:

程序中跑 Valgrind 其会极 大的降低程序运行速度,大约降低 10 倍,而跑 AddressSanitizer 大约只降低 2 倍! 与 valgrind 相比 asan 消耗非常低,甚至可以直接在生产环境中启用 asan 排查跟踪内存问题。

2. AddressSanitizer安装与配置
AddressSanitizer在gcc4.8后被默认加入,成为 gcc 的一部分,但不支持符号信息,无法显示出问题的函数和行数。从 4.9 开始,gcc 支持 AddressSanitizer 的 所有功能。因此 gcc 4.8 以上版本使用 ASAN 时不需要安装第三方库,通过在编译时指 定编译 CFLAGS 即可打开开关。

    如果使用 AddressSanitizer 时报错则需要先安装,Ubuntu 安装命令为:

sudo apt-get install libasan0

如果要使用命令行(gcc/g++),可以使用

  • -fsanitize=address:开启内存越界检测
  • -fsanitize-recover=address:一般后台程序为保证稳定性,不能遇到错误就简单退 出,而是继续运行,采用该选项支持内存出错之后程序继续运行,需要叠加设置 ASAN_OPTIONS= halt_on_error=0 才会生效;若未设置此选项,则内存出错即报错退出
  • -fno-stack-protector:去使能栈溢出保护
  • -fno-omit-frame-pointer:去使能栈溢出保护
  • -g1:表示最小调试信息,通常 debug 版本用-g 即-g2

如果要在CmakeList,则可以调用以下命令target_link_libraries:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fsanitize=address")target_link_libraries(MyTarget  asan)

ASAN_OPTIONS 还需要完成环境变量设置选项,这样当程序出问题的时候我们可以立刻查到log情况:

halt_on_error=0:检测内存错误后继续运行

detect_leaks=1:使能内存泄露检测

malloc_context_size=15:内存错误发生时,显示的调用栈层数为 15

log_path=/home/asan.log:内存检查问题日志存放文件路径

export ASAN_OPTIONS=halt_on_error=0:use_sigaltstack=0:detect_leaks=1:malloc_context_size=15:log_path=/debug/asan.log

当出现问题后我们可以访问log文件,并记录了我们这个程序的错误是ERROR后面的内容 detected memory leaks,说明有内存泄漏。

错误类型有如下一些:

  • (heap) use after free 释放后使用
  • heap buffer overflow 堆缓存访问溢出
  • stack buffer overflow 栈缓存访问溢出
  • global buffer overflow 全局缓冲访问溢出
  • use after return
  • use after scope
  • initializations order bugs
  • memory leaks 内存泄露

1是内存分配的地方,#2是使用的地方。然后后面就是导致程序泄漏的位置,是一个进程的内存偏移形式,我们可以在编译时加-g选项,就可以定位出代码位置,例如:

点击内存泄露检测工具-AddressSanitzer - 古月居可查看全文

  • 45
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值