简介

AddressSanitizer 是一个性能非常好的C/C++ 内存错误探测工具。

它由编译器的插桩模块和替换了malloc函数的运行时库组成。

这个工具可以探测如下这些类型的错误:

  • 对堆、栈和全局内存的访问越界(堆缓冲区溢出,栈缓冲区溢出,和全局缓冲区溢出)
  • UAP(Use-after-free,悬挂指针的解引用,或者说野指针)
  • Use-after-return(无效的栈上内存,运行时标记 ASAN_OPTIONS=detect_stack_use_after_return=1)
  • Use-After-Scope (作用域外访问,clang标记-fsanitize-address-use-after-scope)
  • 内存的重复释放 (double-free)
  • 初始化顺序的BUG
  • 内存泄漏 (memory leak)

使用

CentOS7环境下编译器gcc 4.8.5为例 (版本支持: gcc version > 4.8)

  1. 安装对应系统版本和gcc版本的libasan (搜索libasan相关包: pkgs.org):
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/libasan-4.8.5-39.el7.x86_64.rpm
yum install -y libasan-4.8.5-39.el7.x86_64.rpm
  1. 编译源码的时候只需要加上以下编译参数即可:
-fsanitize=address -fno-omit-frame-pointer -g
  1. 若项目是以CMake作为构建工具, 可按如下做法修改:
add_definitions("-fsanitize=address -fno-omit-frame-pointer -lasan")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -lasan")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -lasan")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address -fno-omit-frame-pointer -lasan")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address -fno-omit-frame-pointer -lasan")

测试例子

源码:

#include <iostream>

int main(int argc, char** argv)
{
int a[5];
int index=6;
int retval=a[index];
std::cout << "Ret :" << retval << std::endl;
return retval;
}

编译:

g++ -g -std=c++11 -fsanitize=address -fno-omit-frame-pointer test.cpp -o test

运行./test后报错:

=================================================================
==7708==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffc32facb68 at pc 0x401610 bp 0x7ffc32facae0 sp 0x7ffc32facad0
READ of size 4 at 0x7ffc32facb68 thread T0
#0 0x40160f in main test.cpp:8
#1 0x7fefe78a8504 in __libc_start_main (/lib64/libc.so.6+0x22504)
#2 0x401448 (./test+0x401448) Address 0x7ffc32facb68 is located in stack of thread T0 at offset 56 in frame
#0 0x401525 in main ./test.cpp:5 This frame has 2 object(s):
[32, 52) 'a' <== Memory access at offset 56 overflows this variable
[96, 144) 'm'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ./test.cpp:8 main
Shadow bytes around the buggy address:
0x1000065ed910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000065ed920: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000065ed930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000065ed940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000065ed950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1000065ed960: 00 00 00 00 00 00 f1 f1 f1 f1 00 00 04[f4]f2 f2
0x1000065ed970: f2 f2 00 00 00 00 00 00 f4 f4 f3 f3 f3 f3 00 00
0x1000065ed980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000065ed990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000065ed9a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000065ed9b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Contiguous container OOB:fc
ASan internal: fe
==7708==ABORTING

可以看到报错提示栈缓冲区溢出 ERROR: AddressSanitizer: stack-buffer-overflow, 通过调查源码可以发现程序对栈区内存上的数组a的访问越界了。

实践经验

  • 项目的构建方案应当有编译选项可以随时启用/关闭ASAN
  • 项目送测阶段可以打开ASAN以帮助暴露更多的低概率诡异问题
  • 请勿在生产版本中启用ASAN, 其会降低程序运行速度大概2-5倍 (特殊情况除外)
  • 实际开发测试过程中通过ASAN扫出的常见问题有:
  • 多线程下临界资源未加保护导致同时出现读写访问, 解决方案一般是对该资源恰当地加锁即可
  • 内存越界, 如申请了N字节的内存却向其内存地址拷贝大于N字节的数据, 这种情况在没有开启ASAN的情况下一般都很难发现

AddressSanitizer —— ASAN分析内存错误的更多相关文章

  1. 应用 AddressSanitizer 发现程序内存错误

    作为 C/ C++ 工程师,在开发过程中会遇到各类问题,最常见便是内存使用问题,比如,越界,泄漏.过去常用的工具是 Valgrind,但使用 Valgrind 最大问题是它会极大地降低程序运行的速度, ...

  2. 面向开发的内存调试神器,如何使用ASAN检测内存泄漏、堆栈溢出等问题

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 目录 介绍 如何使用 ASAN 检测内存泄漏 检测悬空指针访问 检测堆溢出 C++ 中的new/delete不匹配 检测栈 ...

  3. linux c++ 内存泄漏检测工具:AddressSanitizer(ASan)

    1.介绍 AddressSanitizer(ASan),该工具为gcc自带,4.8以上版本均可以使用. 2.使用 编译的方式很简单,只需要添加 -fsanitize=address -g 即可,如 g ...

  4. Linux mem 2.7 内存错误检测 (KASAN) 详解

    文章目录 1. 简介 2. Shadow 区域初始化 3. 权限的判断 3.1 read/write 3.2 memxxx() 4. 权限的设置 4.1 buddy 4.1.1 kasan_free_ ...

  5. 使用Memory Analyzer tool(MAT)分析内存泄漏(二)

    转载自:http://www.blogjava.net/rosen/archive/2010/06/13/323522.html 前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那 ...

  6. android 中如何分析内存泄漏

    转载:http://blog.csdn.net/fulinwsuafcie/article/details/8363218 前提条件: 1,电脑安装了java 运行环境 2,手机端开启了 USB 调试 ...

  7. 使用Memory Analyzer tool(MAT)分析内存泄漏

    前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那么字字斟酌.上周末回了趟成都办事,所以本文来迟了.K117从达州经由达成线往成都方向走的时候,发现铁路边有条河,尽管我现在也不知道 ...

  8. [转]C++常见内存错误汇总

    在系统开发过程中出现的bug相对而言是比较好解决的,花费在这个上面的调试代价不是很大,但是在系统集成后的bug往往是难以定位的bug(最好方式是打桩,通过打桩可以初步锁定出错的位置,如:进入函数前打印 ...

  9. Android 性能优化之使用MAT分析内存泄露问题

    我们平常在开发Android应用程序的时候,稍有不慎就有可能产生OOM,虽然JAVA有垃圾回收机,但也不能杜绝内存泄露,内存溢出等问题,随着科技的进步,移动设备的内存也越来越大了,但由于Android ...

随机推荐

  1. 文件误删了怎么办,EasyRecovery来帮忙

    哈喽大家好!又到了年底冲业绩的时候了,每逢这个时候,收拾自己的电脑就和收拾放假一样,令人头秃,不是这个文件丢了,就是那个数据没了,不管您是为论文头秃发愁的学生,还是朝九晚五的上班族,又或者是日进斗金的 ...

  2. 怎么用思维导图软件iMindMap整理发文思路

    如果你是一个普通的博客作者,那么你就应该明白在枯竭时寻找灵感就像是一场噩梦,即使你有一千个想法,但是你无法将它们关联起来也是无用的,所以,为什么不试试iMindMap思维导图呢,尝试创新,进行组建,你 ...

  3. 企业级LINUX自动化运维工具Ansible实战课程下载

    什么是Ansible? Ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.chef.func.fabric)的优点,实现了批量系统配置.批量程序部署.批量 ...

  4. Redis 基础数据结构之一:string(字符串)

    Redis 有 5 种基础数据结构,分别为:string (字符串).list (列表).set (集合).hash (哈希) 和 zset (有序集合),Redis存储数据的结构是键值对形式的. 首 ...

  5. Running Median POJ - 3784

    本题使用对顶堆做法. 为了动态维护中位数,我们可以建立两个堆 :一个大根对,一个小根堆. 用法:在动态维护的过程中,设当前的长度为length,大根堆存从小到大排名 $1 \thicksim \dfr ...

  6. 记 · ElemetnUI + Vue v-if 视图切换踩过的那些坑

    使用EleUI 做一个用户登录窗口,需要用v-if 动态切换三个表单:手机登录.账密登录和密码找回.其中需要实现一个重置表单的功能,但其间出了一些小bug.密码找回表单中有三个表单项,手机登录和账密登 ...

  7. kafka producer 概要(看源码前,最好能掌握)

        kafakproducer概要(看源码前,最好能理解) 摘要 kafak 被设计用来作为一个统一的平台来处理庞大的数据的实时工具,在设计上有诸多变态的要求 它必须具有高吞吐量才能支持大量事件流 ...

  8. Java基础教程——变量

    变量 变量(variable)可以理解为一个"有名称的容器",用于装各种不同类型的数据.编程人员通过对变量的访问和修改,操作内存中的数据. 对变量的理解:https://www.c ...

  9. Java中的单例模式最全解析

    单例模式是 Java 中最简单的设计模式之一,它是指一个类在运行期间始终只有一个实例,我们就把它称之为单例模式.它不但被应用在实际的工作中,而且还是面试中最常考的题目之一.通过单例模式我们可以知道此人 ...

  10. 如何解决vue2.0 打包之后 打开index.html出现空白页

    如何解决vue2.0 打包之后 打开index.html出现空白页 1.打包之前修改三个文件       1.1.第一步,找到build文件,在webpack.prod.conf.js 第25行左右 ...