Sanitizers简介
Address Sanitizer(ASAN)是一个快速的内存错误检测工具。它非常快,只拖慢程序两倍左右(比起Valgrind快多了)。它包括一个编译器instrumentation模块和一个提供malloc()/free()替代项的运行时库。GCC从4.8版本开始支持Address和Thread Sanitizer,4.9版本开始支持Leak Sanitizer和UB 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 -fsanitize=address -fsanitize-recover=all -fsanitize=leak")
还可以通过如下函数:
add_compile_options(-fsanitize=address -fsanitize-recover=all -fsanitize=leak)
add_link_options(-fsanitize=address -fsanitize-recover=all -fsanitize=leak)
注意事项
(1)ASan发现内存访问违规的时,应用程序并不会自动崩溃。
export ASAN_OPTIONS='abort_on_error=1'/export ASAN_OPTIONS='abort_on_error=1'/
(2) 在ARM用可能会有问题,但是我没有开发板,有感兴趣的试一下告诉我一声能不能用啊
(3)
————————————————————————————————————————————————————————————————————————————————————————————————————————————
2023.01.03 补充
群里有人说这个工具还是有好多发现不了的内存泄漏,有人推荐:
1、gperftools/或者dump出来,strings统计下词出现频率
2、pprof gperftools,利用tcmalloc跟这个工具排查
参考文献
- 如何使用ASAN检测内存泄漏、堆栈溢出等问题
- 内存检测工具sanitizer[内存泄漏、内存越界] VS valgrind
- Address Sanitizer(Asan)原理及实战定位
- ASAN编译选项(中文)