内存分析工具的使用——AddressSanitizer

news2024/10/12 0:29:28

一、c/c++中的内存问题

memory corruption,内存崩溃或者说内存损坏。在c/c++程序中,有相当一部分的Bug是由内存引起的,也就是刚刚提到的内存崩溃。说得再通俗一些,往往和内存的非法访问有关。内存问题,轻则导致程序失能,中则导致程序崩溃,重则引起系统瘫痪。
因此,在c/c++编程的过程中,对内存的管理要求非常严格。但灵活多变的指针往往又让很多开发者无法安全的进行内存的处理,即使在新的C++标准中使用了智能指针或者说自行进行了RAII的封装,仍然有可能造成指针引起的内存错误。当然,并不是说c/c++中指针是内存问题的万恶之源,其它情况如数组越界访问等均可以出现类似的问题。
基于上面的内存的问题,很多针对内存进行控制的相关工具也有很多。其中,有静态内存检查工具(Cppcheck等)和动态内存检查工具(valgrind等)。本文介绍一个动态内在检查工具,GAS。

二、GAS

GAS,google address sanitizer,也称为ASan,它是google公司开发的一个快速的内在检测工具。相比于Valgrind对程序的影响,ASan的速度那相当快了。要想监测内存,最好的办法是什么?当然是替换掉编译器的相关内存管理接口了。ASan就提供了一个插桩模块(编译器检测模块LLVM pass)和一个提供malloc等函数替代接口的运行时库。
ASan早期就与LLVM(3.1)进行了结合,将其插桩模块整合到了Clang项目中。后来在Gcc4.8中,也整合了GAS的相关模块,但其配合不太完善,所以推荐使用Gcc4.9以上版本。ASan还有一个专门提供给内核使用的版本KASAN,有兴趣可以搞一下。

三、基本原理

ASan使用的内存检测机制是使用影子内存(shadow memory)来记录当前内存是否可以安全访问的方式。其通过影子内存与常规内存(normal memory)进行映射以期安全的管理内存。通过代码插桩来检查程序运行时影子内存的状态。
当编译器运行时,其通过替代的分配内存管理接口,在内存分配和回收后的区域进行“投毒”(poisoned),形成所谓的有毒区域(如果有visual studio系列的反汇编的经验会很容易理解这段话,其实就是对内存进行二次标记管理并设置相关的安全管理区域),这个其它的动态内存管理如数组安全检测的机理基本类似。关于影子内存映射的机理和相关细节,请查阅谷歌相关论文,此处不再赘述。

四、ASan支持的内存检查

ASan对常见的内存问题都进行了支持,主要包括下面几点:
1、Use after free
这个比较好理解,它主要是指堆(Heap)内存在释放后又被重新使用。这是一种非常常见的内存问题,类似于下面的代码:

A *a = new A();
delete a;
a->pid = 0;

2、Heap buffer overflow
这也是一种比较常见的内存错误,即堆内存溢出,也就是越界:

char * p = new char[10];
p[11] = 2;

3、Stack buffer overflow
说过了堆溢出怎么能不提栈溢出呢,这个就不举例子了,太简单多见了。
4、Global buffer overflow
全局缓冲区溢出,这都和堆溢出类似。
5、Use after return
返回值使用无效内存,典型的就是返回一个临时变量的指针或引用,看下面的代码:

int * getData(){
  int tmp[10];
  return tmp;
}
int * d = getData();

6、Use after scope
使用作用域外的内存空间,和上面的有些类似。看下面的代码:

for(int i = 0;i< 10;i++){}
int p = i;

7、Initialization order bugs
初始化顺序不同引用的问题,这个比较符合C++的特性。这个在前面的分析过好多次,最典型的就是库中的全局变量与调用者之间调用之间的顺序问题,静态变量也有这种可能的现象。
8、Memory leaks
内存泄露,这可是写c/c++程序员的“亲亲”。不管多么高深的开发者,几乎都会遇到这个问题。但有一句话需要说明:内存泄露不可怕,可怕是内存泄露的累积。

五、应用

在基本了解了ASan后,下面举一个例子来进行实践一把。使用ASan的主要步骤分为:

1、编写测试程序

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

int heapOver() {
  char *pBuf = (char *)malloc(10 * sizeof(char));
  memcpy(pBuf + 10, "abcd1234", 8);
  free(pBuf);

  return 0;
}
int *getData() {
  int *arr = new int[10];
  delete arr;
  return arr;
}
int main() {
  heapOver();
  int arr[10] = {0};
  int d = arr[11];

  int *p = getData();
  delete p;

  return 0;
}

2、在编译时增加相关参数
gcc中增加-fsanitize=address选项;如果想获得较好性能,建议增加-O1或更高编译优化选项;增加fno-omit-frame-pointer选项可以提供更友好的堆栈回溯信息

3、编译并运行:

#编译:注意如果不加-g选项,则无法准确的显示出问题的源码位置,可自行测试一下不带-g
~/project/ASanTest$ g++  -fsanitize=address -fno-omit-frame-pointer -g -o asanTest main.cpp
#运行
~/project/ASanTest$ ./asanTest 
=================================================================
==94673==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000001a at pc 0x7f6acbe3a2c3 bp 0x7ffde51ff060 sp 0x7ffde51fe808
WRITE of size 8 at 0x60200000001a thread T0
    #0 0x7f6acbe3a2c2 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #1 0x55b7993f9381 in heapOver() /home/qt65_project/ASanTest/main.cpp:8
    #2 0x55b7993f9477 in main /home/fqt65_project/ASanTest/main.cpp:19
    #3 0x7f6acb629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #4 0x7f6acb629e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #5 0x55b7993f9284 in _start (/home//qt65_project/ASanTest/asanTest+0x1284)

0x60200000001a is located 0 bytes to the right of 10-byte region [0x602000000010,0x60200000001a)
allocated by thread T0 here:
    #0 0x7f6acbeb4887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x55b7993f935e in heapOver() /home/qt65_project/ASanTest/main.cpp:7
    #2 0x55b7993f9477 in main /home/fqt65_project/ASanTest/main.cpp:19
    #3 0x7f6acb629d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00[02]fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: 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
==94673==ABORTING

大家可以依次的进行测试,就会将三种类型的问题,都在运行时暴露出来。分别报得错误是“堆溢出、栈溢出和分配释放不匹配”。而且描述的非常详细和准确,大家可以自己动手实践一把。

六、总结

工欲善其事,必先利其器。不是常说,某某是编程界的瑞士军刀么。其实,只要是刀,用好了都会起到事半功倍的效果。要想写出好的代码,除了有思想上的指导,在实践中熟练的应用各种开发工具也是必不可少的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2206351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

生成式专题的第二节课--DCGAN

一、DCGAN基础概念 DCGAN&#xff08;Deep Convolutional Generative Adversarial Network&#xff0c;即深度卷积生成对抗网络&#xff09;&#xff0c;于2016年提出&#xff0c;是一种深度学习模型&#xff0c;是生成对抗网络&#xff08;GAN&#xff09;的一种变体&#xf…

国产 HDMI 发送芯片,兼容 HDMI1.4b 及 HDMI 1.4b 下的视频 3D 传输格式。

最高分辨率高达 4K30Hz&#xff0c;最高采样率达到 300MHz.支持 YUV 和 RGB 之间的色彩空间转 换&#xff0c;数字接口支持 YUV 以及 RGB 格式输入的 IIS 接口以及 S/PDIF 接口支持高清音频的 传输&#xff0c;其中 S/PDIF 接口既可以兼容IEC61937 标准下的压缩音频传输&#x…

图像增强——传统算法伽马校正实现暗光增强(附Python代码)

&#x1f4aa; 专业从事且热爱图像处理&#xff0c;图像处理专栏更新如下&#x1f447;&#xff1a; &#x1f4dd;《图像去噪》 &#x1f4dd;《超分辨率重建》 &#x1f4dd;《语义分割》 &#x1f4dd;《风格迁移》 &#x1f4dd;《目标检测》 &#x1f4dd;《图像增强》 &a…

OpenSearch迁移方案

一、背景 因业务需要迁移Opensearch 集群&#xff0c;当前集群数据量高达21TB&#xff0c;采用常规工具进行迁移估计不可取&#xff0c;需要使用对象存储做中转&#xff0c;进行OpenSearch数据迁移。 二、OpenSearch迁移方案 前期进行OpenSearch数据迁移调研 序号方案诠释备…

java项目之科研工作量管理系统的设计与实现源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的科研工作量管理系统的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 科研工作…

介绍Java

Java简介 Java是一门由Sun公司&#xff08;现被Oracle收购&#xff09;在1995年开发的计算机编程语言&#xff0c;其主力开发人员是James Gosling&#xff0c;被称为Java之父。Java在被命名为“Java”之前&#xff0c;实际上叫做Oak&#xff0c;这个名字源于James Gosling望向…

Basic Pentesting_ 2靶机渗透

项目地址 plain https://download.vulnhub.com/basicpentesting/basic_pentesting_2.tar.gz 修改静态ip 开机按e 输入rw signie init/bin/bash ctrlx 进入编辑这个文件 vi /etc/network/interfaces修改网卡为ens33 保存退出 实验过程 开启靶机虚拟机 ![](https://img-bl…

paimon,基础查询语句测试

基础设置 -- 创建catalog/加载catalog&#xff0c;如果这个catalog已经存在就不会创建&#xff0c;自动加载元数据信息CREATE CATALOG fs_paimon_catalog WITH ( type paimon, warehouse hdfs://wsl01:8020/paimon/catalog ); -- 使用catalog use catalog fs_paimon_catalog…

Java中二维数组-杨辉三角

使用二维数组打印一个10行杨辉三角 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1&#xff09;第一行有1个元素&#xff0c;第n行有n个元素 2&#xff09;每一行的第一个元素和最后一个元素都是1 3&#xff09;从第三行开始&#xff0c;对于非第一个元素和最后一个元素的元素…

差分注意力,负注意力的引入

文章目录 Differential Transformer差分注意力&#xff0c;负注意力的引入相关链接介绍初始化函数多头差分注意力 Differential Transformer差分注意力&#xff0c;负注意力的引入 相关链接 ai-algorithms/README.md at main Jaykef/ai-algorithms (github.com) unilm/Diff…

response和验证码、文件下载操作

目录 Response对象 案例&#xff1a; 1、完成重定向 2、服务器输出字符输出流到浏览器 3、服务器输出字节输出流到浏览器 4、验证码 ServletContext对象 Response对象 功能&#xff1a;设置响应消息 1、设置响应行 格式&#xff1a;HTTP/1.1 200 ok 设置状态码 se…

RabbitMQ 高级特性——死信队列

文章目录 前言死信队列什么是死信常见面试题死信队列的概念&#xff1a;死信的来源&#xff08;造成死信的原因有哪些&#xff09;死信队列的应用场景 前言 前面我们学习了为消息和队列设置 TTL 过期时间&#xff0c;这样可以保证消息的积压&#xff0c;那么对于这些过期了的消…

【更新】上市公司企业机构投资者实地调研数据(2013-2023年)

一、测算方式&#xff1a; 参考《会计研究》逯东&#xff08;2019&#xff09;老师的做法&#xff0c;考虑投资者实地调研的频率和可能性&#xff0c;设立了下述变量来衡量上市公司接待投资者调研情况: 首先&#xff0c;使用年度范围内接待投资者调研的总次数 ( Visitnmb) 作为…

卸载PLSQL及标准卸载流程

目录 1. 卸载PLSQL2. 删除注册表3. 删除数据信息 1. 卸载PLSQL 等待进度条走完 2. 删除注册表 regedit 右击删除 3. 删除数据信息 由于AppData是隐藏文件&#xff0c;需要勾选隐藏的项目。 重启电脑&#xff0c;PLSQL就卸载成功了。

低代码工单管理app评测,功能与效率解析

预计到2030年&#xff0c;低代码平台市场将达1870亿美元。ZohoCreator助力企业构建定制化软件应用&#xff0c;以建筑行业工作订单管理app为例&#xff0c;简化流程&#xff0c;提升管理效率&#xff0c;降低成本。其用户友好界面、自动化管理、跨平台使用及全面报告功能受企业…

项目优化内容及实战

文章目录 事前思考Prometheus 普罗米修斯概述架构安装及使用 Grafana可视化数据库读写分离实战1-PrometheusGrafanaspringboot 事前思考 需要了解清楚&#xff1a;需要从哪些角度去分析实现&#xff1f;使用了缓存&#xff0c;就需要把缓存命中率数据进行收集&#xff1b;使用…

企业在隔离网环境下如何进行安全又稳定的跨网文件交换?

在数字化时代&#xff0c;企业的数据流通如同血液一般重要。然而&#xff0c;当企业内部实施了隔离网环境&#xff0c;跨网文件交换就成了一个棘手的问题。今天我们将探讨在隔离网环境下&#xff0c;企业面临的跨网文件交换挑战&#xff0c;以及如何通过合规的跨网文件交换系统…

数字电路——触发器1(RS和钟控触发器)

触发器&#xff1a;能够存储一位二进制信息的基本单元电路称触发器(Flip-Flop) 特点&#xff1a; 具有两个能自行保持的稳定状态&#xff0c;用来表示逻辑状态的“0”或“1”。具有一对互补输出。有一组控制(激励、驱动)输入。或许有定时(时钟)端CP(Clock Pulse)。在输入信号…

PostgreSQL 16.4安装以及集群部署

1. 环境准备 1.1 主机环境 主机 IP: 192.24.215.121操作系统: CentOS 9PostgreSQL 版本: 16.4 1.2 从机环境 从机 IP: 192.24.215.122操作系统: CentOS 9PostgreSQL 版本: 16.4 2. 安装 PostgreSQL 16.4 在主从两台机器上都需要安装 PostgreSQL 16.4。 2.1 添加 Postgre…

银行卡基础信息查询 API 对接说明

本文将介绍一种 银行卡基础信息查询 API 对接说明&#xff0c;它可用于银行卡基础信息查询。 接下来介绍下 银行卡基础信息查询 API 的对接说明。 申请流程 要使用 API&#xff0c;需要先到 银行卡基础信息查询 API 对应页面申请对应的服务&#xff0c;进入页面之后&#xf…