libasan使用和遇到的问题

介绍

Address Sanitizer(ASan)是一个快速的内存错误检测工具。它非常快,只拖慢程序两倍左右(比起Valgrind快多了)。它包括一个编译器instrumentation模块和一个提供malloc()/free()替代项的运行时库。
从gcc 4.8开始,AddressSanitizer成为gcc的一部分。当然,要获得更好的体验,最好使用4.9及以上版本,因为gcc 4.8的AddressSanitizer还不完善,最大的缺点是没有符号信息。

编译

在gcc 4.8以上,编译器中带有libasan.a ,编译时加上

CFLAGS += -fsanitize=address  -fno-omit-frame-pointer -static-libasan
LDFLAGS += -fsanitize=address  -fno-omit-frame-pointer -static-libasan
编译,链接时都加上liasan选项。
-fsanitize=address 是开启内存越界检测
-fno-omit-frame-pointer 是去使能栈溢出保护
-static-libasan 是静态链接asan
静态链接的好处是,在编译时gcc会处理好asan,避免动态链接的asan依赖报错

问题

运行时,os内存不断减少,最后触发OOM;
触发OOM的原因是free的内存被放在了libasan的隔离区,而这个隔离区默认值太大,导致OS内存耗尽。(查到的默认的隔离区上限为 256M,随着 free内存的增加触发了隔离区的清理,所以先前放在隔离区的内存会被归还给系统)

默认隔离区大小,参考资料:https://zhuanlan.zhihu.com/p/382994002

设置libasan 隔离区大小

#内存cache可缓存free内存大小(KB)
export ASAN_OPTIONS=quarantine_size=102400
#export ASAN_OPTIONS=quarantine_size_mb=100

查找linasan的内存释放流程:

malloc()/free()的处理
运行时库用自己的函数替换malloc() / free()。
malloc()在缓存前后分配保护区。缓存本身标记为unpoisoned,保护区标记为poisoned。
free() 将整个区域,包括缓存和保护区,都标记为poisoned,并将该区域放入一个特别的队列中,以保证malloc()在相当长的时间内不会再次使用它)。

libasan 除了有编译选项,还有很多运行选项:

2、ASAN运行选项
2.1 ASAN_OPTIONS设置
ASAN_OPTIONS是Address-Sanitizier的运行选项环境变量。
# halt_on_error=0:检测内存错误后继续运行
# detect_leaks=1:使能内存泄露检测
# malloc_context_size=15:内存错误发生时,显示的调用栈层数为15
# log_path=/home/xos/asan.log:内存检查问题日志存放文件路径
# suppressions=$SUPP_FILE:屏蔽打印某些内存错误
export ASAN_OPTIONS=halt_on_error=0:use_sigaltstack=0:detect_leaks=1:malloc_context_size=15:log_path=/home/xos/asan.log:suppressions=$SUPP_FILE

除了上述常用选项,以下还有一些选项可根据实际需要添加:
# detect_stack_use_after_return=1:检查访问指向已被释放的栈空间
# handle_segv=1:处理段错误;也可以添加handle_sigill=1处理SIGILL信号
# quarantine_size=4194304:内存cache可缓存free内存大小4M
ASAN_OPTIONS=${ASAN_OPTIONS}:verbosity=0:handle_segv=1:allow_user_segv_handler=1:detect_stack_use_after_return=1:fast_unwind_on_fatal=1:fast_unwind_on_check=1:fast_unwind_on_malloc=1:quarantine_size=4194304

2.2 LSAN_OPTIONS设置
LSAN_OPTIONS是LeakSanitizier运行选项的环境变量,而LeakSanitizier是ASAN的内存泄漏检测模块,常用运行选项有:
# exitcode=0:设置内存泄露退出码为0,默认情况内存泄露退出码0x16
# use_unaligned=4:4字节对齐
export LSAN_OPTIONS=exitcode=0:use_unaligned=4

运行配置项,参考资料:http://cppblog.com/markqian86/archive/2018/06/14/215728.html

其他

如果使用动态的libasan.so
可能需要设置LD_PRELOAD.
libasan.so.x 可以在交叉工具链下搜索。一般都可以搜到静态库和动态库。

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值