ASAN入门参考

news2024/11/19 6:44:20

目录

Asan 是什么?

Asan 功能

缓冲区溢出

悬空指针(引用)

非法释放

内存泄漏

如何使用

实验环境

内存泄露检查

demo1

demo2

堆缓冲区溢出

栈缓冲区溢出

使用悬空指针

使用栈上返回的变量

使用退出作用域的变量/内存

重复释放

输出优化

使用ASAN_OPTIONS参数启动程序

使用asan_symbolize.py脚本

参考 


Asan 是什么?

  1. ASan,即Address Sanitizer,是一个适用于c/c++的动态内存错误检测器,它由一个编译器检测模块(LLVM pass)和一个替换malloc函数的运行时库组成,在性能及检测内存错误方面都优于Valgrind。

Asan 功能

ASan作为编译器内置功能,支持检测各种内存错误:

缓冲区溢出

  1. 堆内存溢出

  2. 栈上内存溢出

  3. 全局区缓存溢出

悬空指针(引用)

  1. 使用释放后的堆上内存

  2. 使用返回的栈上内存

  3. 使用退出作用域的变量

非法释放

  1. 重复释放

  2. 无效释放

内存泄漏

如何使用

  1. 使用ASan时,只需gcc/g++选项加上-fsanitize=address
  2. 如果想要在使用asan的时候获取更好的性能,可以加上O1或者更高的编译优化选项
  3. 想要在错误信息中让栈追溯信息更友好,可以加上-fno-omit-frame-pointer选项
  4. 需要注意的是需要带-g选项,会加入一些调试信息到符号表以供输出使用,不带也可以,如果不带,可能看不到错在哪一行
  5. 需要动态链接库liblsan.so,这个动态链接库会替换掉malloc等系统函数,在自己的malloc中加上统计信息,以达到检测内存泄露的作用。需要注意的点是,我们的环境中可能会有多个gcc或者找不到dso的时候。那么我们可以使用g++ --print-file-name=libasan.so来找到系统的动态链接库(只能是系统的库),这条命令会告诉你so在哪,但在我们的环境中我遇到了一个比较坑的问题。就是so是有,但是so的大小仅为4,里面写着让重新下载so
  6. -fsanitize=,这个有好几种选项

        6.1 asan(内存检测)

        6.2 ubsan(未定义行为检测), 有的时候debug的程序没问题,release的程序会奇奇怪怪的core dump掉,那么你需要做这个检测

        6.3 tsan(线程安全检测),如标题;tsan有一个点需要注意,因为大家代码跑通后一般不会用tsan做检测,再者tsan出来时间不长,一些老的库会有非常多的线程安全问题。再加上检测条件非常严格。所以,大型项目第一用tsan做检查的时候,可能每一行都会有线程安全问题。

        6.4 leak(泄露检测),被6.1包括了

        6.5 如果我们有多个libasan.so,我们需要跟-L/path/to/lib

        6.6 如果提示请加载PRELOAD,那么请export LD_PRELOAD=或者export LD_PRELOAD=/path/to/liblsan.so/libasan.so

实验环境

No LSB modules are available.

Distributor ID: Ubuntu

Description: Ubuntu 20.04.3 LTS

Release: 20.04

Codename: focal

gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

Copyright (C) 2019 Free Software Foundation, Inc.

This is free software; see the source for copying conditions. There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

Copyright (C) 2019 Free Software Foundation, Inc.

This is free software; see the source for copying conditions. There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

内存泄露检查

demo1

#include <iostream>
using namespace std;
int main()
{
    int *p = new int(5);
    std::cout << *p << std::endl;
    return 0;
}

编译:g++ main.cpp -g -llsan -fsanitize=leak

第9行,是个总结,他会告诉你总共泄露了4bytes,这4bytes属于1次开辟的。

4-7行,我们这里只泄露了一次,如果多次的话会有多个4-7行,会告诉你那个线程开辟的空间,哪个线程释放的空间。并且打印出详细的开辟和释放的函数栈,当然我们注意第五行,我们用的malloc已经被替换成lsan下的malloc了。

第2行,错误类型。

demo2

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
char* get_systeminfo()
{
        char *p_system = (char*)malloc(38*sizeof(char));
        strcpy(p_system, "Linux version");
        return p_system;
}
 
int main()
{
        printf("Linux version is:%s", get_systeminfo());
        return 0;

}

编译运行输出:

需带上ASAN_OPTIONS=detect_leaks=1 环境变量参数启程序
编译:
g++ -fsanitize=address -fno-omit-frame-pointer -o memory_leak_test main.cpp
ASAN_OPTIONS=detect_leaks=1  ./memory_leak_test

输出:
=================================================================
==73465==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 38 byte(s) in 1 object(s) allocated from:
    #0 0x7fc23737d808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x55d14d17b21e in get_systeminfo() (/home/wangji/文档/桌面/学习资料/C++/memory_leak_test+0x121e)
    #2 0x55d14d17b24d in main (/home/wangji/文档/桌面/学习资料/C++/memory_leak_test+0x124d)
    #3 0x7fc236d560b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2)

SUMMARY: AddressSanitizer: 38 byte(s) leaked in 1 allocation(s).

堆缓冲区溢出

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char *heap_buf = (char*)malloc(32*sizeof(char));
   memcpy(heap_buf+30, "overflow", 8);//在heap_buf的第30个字节开始,拷贝8个字符
 
   free(heap_buf);
 
   return 0;
}

编译:

gcc -fsanitize=address -fno-omit-frame-pointer -o heap_ovf_test main.c

./heap_ovf_test

可以看到asan报错:==74085==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000000030 at xxxx,下面也列出了发生heap-buffer-overflow时的调用链及heap buffer在哪里申请的。

栈缓冲区溢出

#include <stdio.h>
#include <string.h>
 
int main()
{
        char stack_buf[4] = {0};
        strcpy(stack_buf, "1234");
 
        return 0;
}

编译:

gcc -fsanitize=address -fno-omit-frame-pointer -o stack_ovf_test main.c

./stack_ovf_test

使用悬空指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
        char *p = (char*)malloc(32*sizeof(char));
        free(p);
 
        int a = p[1];
 
        return 0;
}

编译:

gcc -fsanitize=address -fno-omit-frame-pointer -o dang_pointer main.c

./dang_pointer

使用栈上返回的变量

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *ptr;
void get_pointer()
{
        int local[10];
        ptr = &local[0];
        return;
}

int main()
{
        get_pointer();
 
        printf("%d\n", *ptr);
 
        return 0;

}

编译:

启用ASAN_OPTIONS=detect_stack_use_after_return=1标志,才能检测此种内存错误使用的情况

gcc -fsanitize=address -fno-omit-frame-pointer -o use_after_return main.c

ASAN_OPTIONS=detect_stack_use_after_return=1 ./use_after_return

使用退出作用域的变量/内存

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
        int *p;
        {
                int num = 10;
                p = &num;
        }
        printf("%d/n", *p);
 
        return 0;

}

编译:

gcc -fsanitize=address -fno-omit-frame-pointer -o use-after-scope main.c

./use-after-scope

重复释放

#include <stdio.h>
#include <stdlib.h>
 
int main()
{
        char *p = (char*)malloc(32*sizeof(char));
        free(p);
        free(p);
 
        return 0;
}

编译:

gcc -fsanitize=address -fno-omit-frame-pointer -o invalid_free_test main.c

./invalid_free_test

输出优化

使用ASAN_OPTIONS参数启动程序

ASAN_OPTIONS='stack_trace_format="[frame=%n, function=%f, location=%S]"'参数启动程序

使用asan_symbolize.py脚本

输出的调用链中信息更精确,可以对应到代码文件的具体某一行。

参考 

AddressSanitizer · google/sanitizers Wiki · GitHub

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

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

相关文章

逐字稿 | 对比学习论文综述【论文精读】

对比学习在计算机视觉领域的发展历程&#xff0c;4个阶段&#xff1a; 百花齐放&#xff1a;方法、模型、目标函数、代理任务都还没有统一。CV双雄&#xff1a;MOCOv1、SimCLRv1、MOCOv2、SimCLRv2、CPC和CMC的延伸工作、SwaV&#xff0c;这个阶段发展非常迅速&#xff0c;以上…

好莱坞编剧大罢工终于结束;与OpenAI创始人共进早餐;使用DALL-E 3制作绘本分享;生成式AI的基础设施架构 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f525; 好莱坞编剧大罢工终于结束&#xff1a;简单说就是AI妥协了 https://www.wgacontract2023.org/the-campaign/summary-of-the-2023-wga-…

【Pytorch】深度学习之损失函数

文章目录 二分类交叉熵损失函数交叉熵损失函数L1损失函数MSE损失函数平滑L1(Smooth L1)损失函数目标泊松分布的负对数似然损失KL散度MarginRankingLoss多标签边界损失函数二分类损失函数多分类的折页损失三元组损失HingEmbeddingLoss余弦相似度CTC损失函数参考资料 学习目标&am…

CS配合frp上线

代理使用场景 1、拿下远程web服务器 2、webshell链接不稳定&#xff0c;需要使用稳定的木马程序 3、远程服务器无法直接链接攻击者电脑 4、需要借助公网vps转发来自失陷服务器的木马流量 5、借助frp服务端(vps)和客户端(内网攻击者)建立隧道 6、当vps某一个端口收到流量的…

Jenkins更换主目录

Jenkins储存所有的数据文件在这个目录下. 你可以通过以下几种方式更改&#xff1a; 使用你Web容器的管理工具设置JENKINS_HOME环境参数.在启动Web容器之前设置JENKINS_HOME环境变量.(不推荐)更改Jenkins.war(或者在展开的Web容器)内的web.xml配置文件. 这个值在Jenkins运行时…

Ubuntu 启用 root 用户

打开 ubuntu 的终端&#xff0c;现在的命令行是由 zz-virtual-machine:~$ 这几个字母组成&#xff0c;那么这几个字母代表意思为&#xff1a; z当前操作用户是固定格式z-virtual-machine代表的是主机名~代表当前目录名$代表普通用户操作权限#代表 root 用户权限 在安装系统的时…

《论文阅读:Dataset Condensation with Distribution Matching》

点进去这篇文章的开源地址&#xff0c;才发现这篇文章和DC DSA居然是一个作者&#xff0c;数据浓缩写了三篇论文&#xff0c;第一篇梯度匹配&#xff0c;第二篇数据增强后梯度匹配&#xff0c;第三篇匹配数据分布。DC是匹配浓缩数据和原始数据训练一次后的梯度差&#xff0c;DS…

nginx反向代理IIS实现80默认端口,不需要输入端口访问

IIS的网站 端口是8086 Nginx 配置指向IIS的8086 这样可以不用输端口,nginx/confi/nginx.conf server {listen 80;server_name localhost;#charset koi8-r;#access_log logs/host.access.log main;location / {root html ;index index.html index.htm;}location /h…

配电柜远程控制系统:智能化时代的电力管理新篇章

随着科技的发展&#xff0c;电力系统数字化、智能化成为一种趋势。越来越多的市场需求和数字化的政策导向&#xff0c;让配电柜远程控制成为可能&#xff0c;力安科技电易云配电柜远程控制系统应运而生&#xff0c;这种系统利用先进的通信和计算机、人工智能等技术&#xff0c;…

Kafka 开启SASL/SCRAM认证 及 ACL授权(一)认证

Kafka 开启SASL/SCRAM认证 及 ACL授权(一)认证。 kafka安全涉及3部份:传输加密,用户认证与授权,ZK开启ACL(Zookeeper存储了kafka的元数据以及用户信息,默认不开启acl所有用户可改,内网环境机器不对外开放可考虑使用默认不开启ZK ACL)。 官网地址:https://kafka.ap…

dockerfile 搭建lnmp+wordpress,docker-compose搭建lnmp+wordpress

目录 dockerfile 搭建lnmpwordpress 部署nginx&#xff08;容器IP 为 172.18.0.10&#xff09; 部署mysql&#xff08;容器IP 为 172.18.0.20&#xff09; 部署php&#xff08;容器IP 为 172.18.0.30&#xff09; docker-compose搭建lnmpwordpress dockerfile 搭建lnmpword…

LeetCode 2562. 找出数组的串联值【数组,相向双指针】1259

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

电子笔记真的好用吗?手机上适合记录学习笔记的工具

提及笔记&#xff0c;不少人都会和学习挂钩&#xff0c;的确学习过程中我们经常会遇到很多难题&#xff0c;而经常记录笔记可以有效地帮助大家记住很多知识&#xff0c;而且时常拿出笔记查看一下&#xff0c;可方便巩固过去学习的知识。 手机作为大家日常随身携带的工具&#…

golang 拉取 bitbucket.org 私有库

以 bitbucket.org 平台和mac电脑为例 前置条件私库需要给你账号权限&#xff0c;可拉取的权限&#xff0c;否则无法进行正常拉取 我们采用ssh方式&#xff0c;需要在本地生成对应的 rsa 的公钥和私钥&#xff0c;将公钥配置如下图&#xff1a; 在 .ssh/config 写入你的配置 H…

工业环网交换机运行原理

在智能制造领域&#xff0c;工业环网交换机是一种必不可少的网络设备。该技术通过将各种工业设备、传感器和机器人连接到同一网络中&#xff0c;实现了高效的数据传输和快速的信息交流。在本文中&#xff0c;我们将讨论工业环网交换机的运行原理&#xff0c;以帮助您更好地了解…

文心一言 VS 讯飞星火 VS chatgpt (112)-- 算法导论10.2 3题

三、用go语言&#xff0c;用一个单链表L实现一个队列。要求操作 ENQUEUE 和 DEQUEUE 的运行时间仍为O(1)。 文心一言&#xff1a; 在 Go 语言中&#xff0c;使用单链表实现队列的操作&#xff0c;包括入队&#xff08;ENQUEUE&#xff09;和出队&#xff08;DEQUEUE&#xff…

练习之C++[2]

文章目录 1.栈和堆2.new和delete3.内存区域 1.栈和堆 对于栈来讲&#xff0c;生长方向是向下的&#xff0c;也就是向着内存地址减小的方向&#xff1b;对于堆来讲&#xff0c;它的生长方向是向上的&#xff0c;是向着内存地址增加的方向增长.栈区先定义的变量放到栈底&#xf…

官宣!联诚发与康冠科技达成战略合作,全面布局文旅演艺领域!

2023年10月11日&#xff0c;康冠科技&#xff08;股票代码&#xff1a;001308&#xff09;与联诚发LCF签约仪式在联诚发LCF深圳总部顺利举行&#xff0c;双方正式建立战略合作伙伴关系&#xff0c;并将基于自身优势&#xff0c;围绕文旅演艺、XR虚拟拍摄、5G8K、舞台租赁等领域…

基于Springboot实现校园疫情登记防控系统项目【项目源码+论文说明】

基于Springboot实现校园疫情登记平台系统演示 摘要 2019年12月19号中国武汉发生第一例新冠病毒的到来&#xff0c;大家都在听从政府的号召在居家隔离&#xff0c;不管是在城市还是在乡镇、农村&#xff0c;这引起我的注目&#xff0c;设计一套校园疫情防控系统&#xff0c;疫情…

LiveGBS流媒体平台GB/T28181功能-国标流媒体服务同时兼容内网收流外网收流多网段设备收流

LiveGBS流媒体平台GB/T28181功能-国标流媒体服务同时兼容内网收流外网收流多网段设备收流 1、背景2、设备接入播放2.1、查看通道2.2、直播播放 3、默认收流地址配置4、其它网络设备收流配置5、搭建GB28181视频直播平台 1、背景 服务器部署的时候&#xff0c;可能有多个网卡多个…