asan c/c++内存检测

一、ASAN 简介

ASAN(AddressSanitizer 的缩写)是一款面向C/C++语言的内存错误问题检查工具,可以检测如下内存问题:

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

ASAN工具主要由两部分组成:

运行时库
运行时库(libasan.so.x)会接管 malloc 和 free 函数。malloc执行完后,已分配内存的前后(称为“红区”)会被标记为“中毒”状态,而释放的内存则会被隔离起来(暂时不会分配出去)且也会被标记为“中毒”状态。

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

编译前:

*address = ...;  // or: ... = *address;

编译后:

if (IsPoisoned(address)) {
  ReportError(address, kAccessSize, kIsWrite);
}
*address = ...;  // or: ... = *address;

https://github.com/google/sanitizers/wiki/AddressSanitizerFlags

二、ASAN 安装

Ubuntu 安装命令:

sudo apt-get install libasan0

CentOS 安装命令:

sudo yum install libasan

三、ASAN 使用

(1)gcc 编译选项

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

(2)ASAN_OPTIONS 设置

ASAN_OPTIONS是AddressSanitizier的运行选项环境变量。

# halt_on_error=0:检测内存错误后继续运行
# detect_leaks=1:使能内存泄露检测
# malloc_context_size=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=/tmp/asan.log
# env |grep ASAN_OPTIONS

(3)编译运行

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *ptr = (char *)malloc(10);
    ptr = NULL;
    return 0;
}

-g 保留代码文字信息

gcc -g main.c -fsanitize=address -fno-stack-protector -fno-omit-frame-pointer -o main

ASAN_OPTIONS=log_path=/root/test/asan.log ./main

ps:
1,addr2line参数介绍:

-a --addresses:在函数名、文件和行号信息之前,显示地址,以十六进制形式。
-b --target=<bfdname>:指定目标文件的格式为bfdname。
-e --exe=<executable>:指定需要转换地址的可执行文件名。
-i --inlines : 如果需要转换的地址是一个内联函数,则输出的信息包括其最近范围内的一个非内联函数的信息。
-j --section=<name>:给出的地址代表指定section的偏移,而非绝对地址。
-p --pretty-print:使得该函数的输出信息更加人性化:每一个地址的信息占一行。
-s --basenames:仅仅显示每个文件名的基址(即不显示文件的具体路径,只显示文件名)。
-f --functions:在显示文件名、行号输出信息的同时显示函数名信息。
-C --demangle[=style]:将低级别的符号名解码为用户级别的名字。
-h --help:输出帮助信息。
-v --version:输出版本号

2,使用如下脚本可以将asan日志中的(so+偏移地址)转化为(文件+行数)。需安装debuginfo

cat $1|while read line;do
    if [ $(echo $line|grep -o '(.*+.*)'|wc -l) = 1 ];then
        a=$(echo $line|cut -d '(' -f1)
        b=$(echo $line|cut -d '(' -f2|cut -d ')' -f1|awk -F '+' '{print $1}')
        c=$(echo $line|cut -d '(' -f2|cut -d ')' -f1|awk -F '+' '{print $2}')
        if [ -z "$b" ] || [ -z "$c" ]; then
            echo $line
            continue
        fi
        d=$(addr2line -e $b $c)
        if [ $(echo $d|grep '?'|wc -l) = 0 ];then
            echo -e "\t$a($d)"
        else
            echo -e "\t$line"
        fi
    else
        echo $line
    fi
done
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值