内存检测工具Sanitizer(内存泄漏、内存越界)

Sanitizers简介

Address Sanitizer(ASAN)是一个快速的内存错误检测工具。它非常快,只拖慢程序两倍左右(比起Valgrind快多了)。它包括一个编译器instrumentation模块和一个提供malloc()/free()替代项的运行时库

Sanitizers是谷歌发起的开源工具集,包括了AddressSanitizer, MemorySanitizer, ThreadSanitizer, LeakSanitizer,Sanitizers项目本是LLVM项目的一部分,但GNU也将该系列工具加入到了自家的GCC编译器中。GCC从4.8版本开始支持AddressThread Sanitizer,4.9版本开始支持Leak SanitizerUB Sanitizer,这些都是查找隐藏Bug的利器。(gcc 4.9及以上版本体验更好

valgrind特点

工具相对简单,对于一些复杂的内存泄露可能无法解析出来而且有一个问题就是只有检测的进程退出后才会输出内存泄露信息

ASAN特点

sanitizer可以在检测到内存泄露第一时间立刻终止进程,并且它可以深入检测(随应用进程一起编译)

ASAN支持检测的内存问题

  • 使用已释放内存(野指针)
  • 堆内存越界(读写)
  • 栈内存越界(读写)
  • 全局变量越界(读写)
  • 函数返回局部变量
  • 内存泄漏

使用方法

ASAN工具最常用的编译选项如下:

  • -fsanitize=address #开启地址越界检查功能
  • -fno-omit-frame-pointer #开启后,可以出界更详细的错误信息
  • -fsanitize=leak #开启内存泄露检查功能
  • -ggdb #方便调试

(1)CMake中使用

set(CMAKE_CXX_FLAGS	 -std=c++11 -m64 -Wno-write-strings -fexceptions  -fno-inline -rdynamic -fsanitize=address -fsanitize-recover=all  -fsanitize=leak)  

注意事项
(1)ASan发现内存访问违规的时,应用程序并不会自动崩溃。 这是由于在使用模糊测试工具时,它们通常都是通过检查返回码来检测这种错误。当然,我们也可以在模糊测试进行之前通过将环境变量 ASAN_OPTIONS修改成如下形式来迫使软件崩溃:

export ASAN_OPTIONS='abort_on_error=1'/export ASAN_OPTIONS='abort_on_error=1'/ 

参考文献

  1. 内存检测工具sanitizer[内存泄漏、内存越界] VS valgrind
  2. Address Sanitizer(Asan)原理及实战定位