当前位置: 首页> 玩家福利> 正文

内存泄露检测工具-AddressSanitzer

admin 2025-07-26 147

0.简介

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

内存释放后又被使用;

内存重复释放;

释放未申请的内存;

使用栈内存作为函数返回值;

使用了超出作用域的栈内存;

内存越界访问;

1.AddressSanitzer是怎么做的

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

编译后:

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

2.AddressSanitizer安装与配置

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

如果使用AddressSanitizer错则需要先安装,Ubuntu安装命令为:
sudoapt-getinstalllibasan0

如果要使用命令行(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(MyTargetasan)

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

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

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

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

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

exportASAN_OPTIONS=halt_on_error=0:use_sigaltstack=0:detect_leaks=1:malloc_context_size=15:log_path=/debug/

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

错误类型有如下一些:

(heap)useafterfree释放后使用

heapbufferoverflow堆缓存访问溢出

stackbufferoverflow栈缓存访问溢出

globalbufferoverflow全局缓冲访问溢出

useafterreturn

useafterscope

initializationsorderbugs

memoryleaks内存泄露

同类文章
  • 最新文章
  • 热门文章
  • 随机阅读
友情链接