首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >内存检测工具——ASan(AddressSanitizer)的介绍和使用

内存检测工具——ASan(AddressSanitizer)的介绍和使用

作者头像
一点sir
发布于 2024-03-20 07:18:10
发布于 2024-03-20 07:18:10
2.7K01
代码可运行
举报
文章被收录于专栏:python教程python教程
运行总次数:1
代码可运行

ASan介绍

ASan全称AddressSanitizer,是一种内存错误检测工具,目的是帮助开发者检测和调试内存相关的问题,如使用未分配的内存、使用已释放的内存、堆内存溢出等。ASan是由Google开发的,广泛用于C、C++等语言的代码中。

ASan的工作原理是在编译时将额外的代码插入到目标程序中,对内存的读写操作进行检测和记录。当程序运行时,ASan会监测内存访问,一旦发现内存访问错误,比如越界访问、释放后再次访问等,会立即输出错误信息并中断程序执行,同时提供详细的报告帮助开发者定位问题的源头。

通过使用ASan,开发者可以在早期阶段发现和解决潜在的内存错误问题,有效提高程序的稳定性和安全性。ASan在调试阶段是一个非常有用的工具,但由于其会引入一些性能开销,因此在生产环境中通常不建议启用ASan。

ASan使用

要使用ASan,你需要使用支持ASan的编译器,如Clang或GCC,并开启ASan相关的编译选项。

  1. 使用Clang编译器,在终端执行以下命令:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
clang -fsanitize=address -g your_program.c -o your_program
  1. 使用GCC编译器,在终端执行以下命令:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
gcc -fsanitize=address -g your_program.c -o your_program

在上述命令中,-fsanitize=address是ASan的编译选项,用于开启ASan。-g选项用于生成调试符号,以支持调试和定位错误。当然,我们也可以通过环境变量的方式加入ASan编译选项,然后编译额时候需要加上环境变量,一般是CFLAGS或者CXXFLAGS。更推荐这种方式,因为通过makefile方式编译的时候,这种方式经常见。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export CFLAGS="-fsanitize=address -g $CFLAGS"
gcc $CFLAGS your_program.c -o your_program

编译完成后,运行生成的可执行文件,ASan会在运行时监测程序的内存访问情况,并在发现错误时提供详细的错误信息,包括错误的位置和类型。

下面是一个使用C语言编写的示例程序,可以用来使用ASan进行内存错误检测

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>
#include <stdlib.h>

void leak_memory() {
    int* p = malloc(sizeof(int) * 10);
    // 没有释放内存,导致内存泄漏
}

int main() {
    int* arr = malloc(sizeof(int) * 5);
    arr[5] = 10; // 内存访问越界错误

    free(arr); // 使用 free 释放内存

    int* p = malloc(sizeof(int));
    free(p); // 使用 free 释放内存

    int* q = NULL;
    *q = 5; // 使用空指针访问内存错误

    leak_memory();

    return 0;
}

编译并运行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
gcc $CFLAGS  asan.c -o asan
./asan 

一切顺利的话,会输出下面这种异常。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
=================================================================
==296710==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xffff7b700b64 at pc 0x000000400810 bp 0xffffd7b963b0 sp 0xffffd7b963a0
WRITE of size 4 at 0xffff7b700b64 thread T0
    #0 0x40080c in main /home/test/asan.c:11
    #1 0xffff7f38df38 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #2 0xffff7f38e004 in __libc_start_main_impl ../csu/libc-start.c:409
    #3 0x4006ac in _start (/home/test/asan+0x4006ac)

0xffff7b700b64 is located 0 bytes to the right of 20-byte region [0xffff7b700b50,0xffff7b700b64)
allocated by thread T0 here:
    #0 0xffff7f5a6080 in malloc (/usr/lib64/libasan.so.6+0xa9080)
    #1 0x4007b0 in main /home/test/asan.c:10
    #2 0xffff7f38df38 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #3 0xffff7f38e004 in __libc_start_main_impl ../csu/libc-start.c:409
    #4 0x4006ac in _start (/home/test/asan+0x4006ac)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/test/asan.c:11 in main
Shadow bytes around the buggy address:
  0x200fef6e0110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e0120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e0130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e0140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e0150: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x200fef6e0160: fa fa fa fa fa fa fa fa fa fa 00 00[04]fa fa fa
  0x200fef6e0170: 00 00 00 fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e0180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e0190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e01a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x200fef6e01b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==296710==ABORTING

看堆栈调用信息可以看到

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#0 0x40080c in main /home/test/asan.c:11

asan.c文件中的第11行出现了异常,我们看第11行可以知道,只有5个元素,却要访问第6个元素,导致了数组溢出。 如果你修改好了第11行,重新编译运行,会发现还会有其他异常,可以动手自己实验,把这个程序修复好。

需要特别特别注意的是,ASan会增加程序的运行时间和内存开销,因此主要用于调试和测试阶段,特别不建议在生产环境中启用。

ASan其他选项

除了 -fsanitize=address 外,还有其他 AddressSanitizer 相关的编译选项可供选择。以下是一些常用的 AddressSanitizer 编译选项及其作用:

  1. Memory Sanitizer (-fsanitize=memory):用于检测对未初始化内存或使用已释放内存的操作。这个选项可以帮助发现一些难以察觉的内存错误。
  2. UndefinedBehaviorSanitizer (-fsanitize=undefined):用于检测未定义行为,例如整数溢出、空指针解引用等问题。这有助于发现代码中的潜在 bug。
  3. Thread Sanitizer (-fsanitize=thread):用于检测多线程程序中的数据竞争和死锁问题。这个选项可以帮助识别并修复多线程程序中的并发 bug。
  4. Address Sanitizer with Leak Detection (-fsanitize=leak):启用 AddressSanitizer 的同时,也检测内存泄漏问题。这个选项有助于发现代码中的内存泄漏 bug。
  5. Coverage Sanitizer (-fsanitize=coverage):用于生成代码覆盖率报告,检测程序中哪些部分被执行过。这个选项通常用于代码覆盖率测试和分析。
  6. Kernel Address Sanitizer (-fsanitize=kernel-address):针对 Linux 内核模块开发,用于检测内核中的内存错误。

参考资料

以下是一些比较权威的关于AddressSanitizer的资料,大多数都是英文,有兴趣可以看看。

https://clang.llvm.org/docs/AddressSanitizer.html

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

https://learn.microsoft.com/zh-tw/cpp/sanitizers/asan

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
asan内存检测工具实例
GCC和CLANG都已经集成了功能,编译时加编译选项即可。主要是-fsanitize=address,其他便于调试。
mingjie
2023/10/13
8160
Linux如何调试内存泄漏
内存泄漏是指由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。
C语言与CPP编程
2020/12/02
6.7K0
sanitizer工具集
Sanitizers是谷歌发起的开源工具集,包括了Address Sanitizer, undefined behavior Sanitizer, Thread Sanitizer, Leak Sanitizer。GCC从4.8版本开始支持Address sanitizer和Thread Sanitizer,4.9版本开始支持Leak Sanitizer和undefined behavior Sanitizer。
全栈程序员站长
2022/11/17
1.4K0
Linux下内存检测工具asan使用介绍
ASAN(Address-Sanitizier)早先是LLVM中的特性,后被加入GCC 4.8,在GCC 4.9后加入对ARM平台的支持。因此GCC 4.8以上版本使用ASAN时不需要安装第三方库,通过在编译时指定编译CFLAGS即可打开开关。
lcyw
2022/06/10
9.7K0
LLVM 工具系列 - Address Sanitizer 基本原理介绍及案例分析(1)
LLVM 提供了一系列的工具帮助 C/C++/Objc/Objc++ 开发者检查代码中可能的潜在问题,这些工具包括 Address Sanitizer,Memory Sanitizer,Thread Sanitizer,XRay 等等, 功能各异。
JoeyBlue
2023/01/08
2.9K0
LLVM 工具系列 - Address Sanitizer 基本原理介绍及案例分析(1)
android native内存检测方案(二)
android native 代码内存泄露 定位方案(一) 什么是 AddressSanitizer clang 是一个 C、C++、Objective-C 编程语言的编译器前端。它采用 了底层虚拟机作为其后端。它的目标是提供一个 GNU 编译器套装 (GCC)的替代品, 作者是克里斯·拉特纳,在苹果公司的赞助下进 行开发。 AddressSanitizer 是 clang 中的一个内存错误检测器,它可以检测到 以下问题: Out-of-bounds accesses to heap, stack an
用户1263308
2018/02/02
4.7K0
android native内存检测方案(二)
Kasan - Linux 内核的内存检测工具
https://www.ibm.com/developerworks/cn/linux/1608_tengr_kasan/index.html
Linux阅码场
2019/10/08
6.1K0
Kasan - Linux 内核的内存检测工具
NDK(C++)开发中如何使用 ASan 检测内存错误
ASan 是 Address Sanitizer 简称,它是是一种基于编译器用于快速检测原生代码中内存错误的工具。
字节流动
2021/05/14
3.3K0
NDK(C++)开发中如何使用 ASan 检测内存错误
在使用asan的时候,如果我们想关闭/取消:use-after-poision 检测
使用这个allow_user_poisoning=0,来取消 以这个例子为例: // example1.cpp // use-after-poison error #include <stdlib.h> extern "C" void __asan_poison_memory_region(void *, size_t); int main(int argc, char **argv) { char *x = new char[16]; x[10] = 0; __asan_poi
Gxjun
2021/11/10
1.8K0
技术解码 | 内存问题的分析与定位
本期的技术解码,为您解析 编程中,内存问题的分析与定位方法 对编程语言设计来说,内存管理分为两大类:手动内存管理(manual memory management) 和垃圾回收(garbage collection). 常见的如C、C++使用手动内存管理,Java使用垃圾回收。本文主要关注手动内存管理。 GC GC使内存管理自动化,缺点是引入了GC时不可预测的暂停(unpredictable stall),对实时性要求高的场景不适用。现代的GC实现一直朝着减小“stop-the-world"影
腾讯云音视频
2021/04/29
4.7K0
应用 AddressSanitizer 发现程序内存错误
作为 C/ C++ 工程师,在开发过程中会遇到各类问题,最常见便是内存使用问题,比如,越界,泄漏。过去常用的工具是 Valgrind,但使用 Valgrind 最大问题是它会极大地降低程序运行的速度,初步估计会降低 10 倍运行速度。而 Google 开发的 AddressSanitizer 这个工具很好地解决了 Valgrind 带来性能损失问题,它非常快,只拖慢程序 2 倍速度。
NebulaGraph
2020/02/19
2.8K0
应用 AddressSanitizer 发现程序内存错误
启用内存泄漏/越界检查工具
只需要添加几行编译选项即可启用内存泄漏/越界检查工具。 注意:目前仅支持GCC 4.8版本以上编译工具,建议使用GCC 4.9版本以上。 0x01 编译选项 开启内存泄露检查功能:-fsanitize=leak 开启地址越界检查功能:-fsanitize=address 开启越界详细错误信息:-fno-omit-frame-pointer 0x02 以Qt工程为例子 .pro项目文件: SOURCES += main.cpp # -fsanitize=leak意思为开启内存泄露检查 QMAKE_CXXFL
Qt君
2020/07/16
4.8K0
Memory Corruption: 代码中的内存损坏问题
大家好,我是默语,擅长全栈开发、运维和人工智能技术。内存损坏(Memory Corruption)是软件开发中一个棘手的问题,可能导致程序崩溃、数据丢失以及安全漏洞。在这篇文章中,我将深入探讨内存损坏的成因、检测方法和解决策略,帮助大家提升代码的稳定性和安全性。关键词:内存损坏、C语言、内存管理、代码安全。
默 语
2024/11/22
5580
Android Address Sanitizer (ASan) 原理简介
前面介绍了 NDK 开发中快速上手使用 ASan 检测内存越界等内存错误的方法,现分享一篇关于 ASan 原理介绍的文章。
字节流动
2021/06/09
5.7K0
Android Address Sanitizer (ASan) 原理简介
Linux内核内存检测工具KASAN
KASAN 是 Kernel Address Sanitizer 的缩写,它是一个动态检测内存错误的工具,主要功能是检查内存越界访问和使用已释放的内存等问题。KASAN 集成在 Linux 内核中,随 Linux 内核代码一起发布,并由内核社区维护和发展。本文简要介绍 KASAN 的原理及使用方法。
233333
2020/11/26
9.7K0
Linux内核内存检测工具KASAN
app针对native部分开启asan压测扫描
天天Lotay
2024/07/11
2050
C++内存问题排查攻略
GCC提供了-fstack-usage选项,能输出每个函数栈的最大使用量。开启后,为每个编译目标创建.su文件,每行包括函数名、字节数、修饰符(static/dynamic/bounded)中的一个或多个。修饰符的含义如下:
腾讯技术工程官方号
2024/08/14
4800
C++内存问题排查攻略
高并发性能测试经验分享(下)
本文介绍了如何通过定制化工具链分析定位解决了因内核栈溢出导致的程序core dump问题,以及如何使用AddressSanitizer工具定位解决了因内存泄漏导致的程序性能问题。通过这些方法,可以更高效地解决程序中的core dump和内存泄漏问题,提高程序的稳定性和性能。
腾讯技术工程官方号
2017/09/05
3.9K0
高并发性能测试经验分享(下)
SoC出现段错误,如何快速定位到故障函数?
定位SoC中段错误的核心思路是“确定范围 -> 提取信息 -> 复现问题 -> 修复”:
不脱发的程序猿
2025/01/07
4450
SoC出现段错误,如何快速定位到故障函数?
linux下c语言内存检测神器asan,专治各种疑难杂症
最近工作中有地方嵌入式程序出现莫名其妙的问题,有时候正常的变量值都会突变了导致问题。
杨永贞
2020/08/04
5.2K0
相关推荐
asan内存检测工具实例
更多 >
LV.2
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验