Address Sanitizer使用指南

Address Sanitizer使用指南提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档文章目录前言一 pandas 是什么 二 使用步骤 1 引入库 2 读入数据总结前言 AddressSanit 使用提示 以下是本篇文章正文内容 下面案例可供参考一 pandas 是什么 示例 pandas 是基于 NumPy 的一种工具 该工具是为了解决数据分析任务而创建的 二 使用步骤 1 引入库代码如下 示例 importnumpya


前言

使用C/C++编程,不可避免地会遭遇各种各样的内存异常。走查代码这种方式定位异常比较低效。在Linux平台下,Address Sanitizer是一个定位程序内存异常的高效分析工具。


一、Address Sanitizer简介

相比Valgrind,Address Sanitizer(ASan)要快很多,只会拖慢程序两倍左右。它包括一个编译器instrumentation模块和一个提供malloc()/free()替代项的运行时库。AddressSanitizer是gcc的一部分,本文采用gcc-7.5.0版本进行演示。

ASan可以检查如下几种内存异常:

  1. 内存错误操作:-fsanitize=address
  2. 多线程竞争:-fsanitize=thread
  3. 内存泄漏:-fsanitize=leak
  4. 未定义操作:-fsanitize=undefined(如:除0、空指针解引用、枚举值超范围、使用未初始化的变量值等)

二、使用步骤

1.安装gcc7.5.0

安装命令:

cd /opt tar -xvzf gcc-7.5.0.tar.gz -C /opt ln -sf /opt/gcc-7.5.0/bin/gcc /usr/bin/gcc-7.5.0 // 避免与系统自带gcc冲突,建立软连接 

2.编译程序

address.h:

#include <memory> #include <tr1/memory> #define MSG_LEN 128 class Cert { 
      public: Cert() { 
      printf("\nCert begin\n"); m_number = 0xFFFFFFFFFFFFFFFF; m_msg = new char[MSG_LEN+1]; memset(m_msg, 0, MSG_LEN + 1); printf("Cert end\n"); } ~Cert() { 
      printf("\n~Cert begin\n"); printf("~Cert end\n"); } public: unsigned long long m_number; char *m_msg; }; typedef std::tr1::shared_ptr<Cert> Cert_Ptr; 

address.cpp:

 /* 注意如下任意一种都不会生成内存检测报告: 1. 使用kill -9结束进程 2. 内存检测报告的文件路径无读写权限 */ #include <stdio.h> #include <string.h> #include <dlfcn.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <signal.h> #include <stdlib.h> #include "address.h" using namespace std; #ifdef Enable_AddressSanitizer static const char* __attribute__((unused)) ENABLE_AS = "Enable_AddressSanitizer"; void signal_handler(int signo); /* 结束进程: kill -s 3 PID */ void signal_handler(int signo) { 
      printf("%s", ENABLE_AS); if(SIGQUIT == signo) /* SIGQUIT: 3 */ { 
      exit(0); } } int output_stderr_to_file(char *logfilepath); int output_stderr_to_file(char *logfilepath) { 
      int result = -1; int logfd = open(logfilepath, O_CREAT|O_RDWR|O_APPEND); if(-1 != logfd) { 
      result = dup2(logfd, STDERR_FILENO); } return result; } #endif void test_func(); int main() { 
      #ifdef Enable_AddressSanitizer char szlogfilename[256] = { 
     0}; const char *pSanitizer = "Analyze_none"; #ifdef Analyze_address pSanitizer = "Analyze_address"; #endif #ifdef Analyze_thread pSanitizer = "Analyze_thread"; #endif #ifdef Analyze_leak pSanitizer = "Analyze_leak"; #endif #ifdef Analyze_undefined pSanitizer = "Analyze_undefined"; #endif char sztime[64] = { 
     0}; time_t tmNowT; time(&tmNowT); struct tm *tmNowS = localtime(&tmNowT); if(0 != tmNowS) { 
      sprintf(sztime, "%04d-%02d-%02d %02d_%02d_%02d", 1900+tmNowS->tm_year,1+tmNowS->tm_mon,tmNowS->tm_mday,tmNowS->tm_hour,tmNowS->tm_min,tmNowS->tm_sec); } else { 
      sprintf(sztime, "%04d-%02d-%02d %02d_%02d_%02d", 1900,1,1,0,0,0); } sprintf(szlogfilename, "./%s_%s.log", pSanitizer, sztime); output_stderr_to_file(szlogfilename); signal(SIGQUIT, signal_handler); #endif while(1) { 
      test_func(); sleep(1); } return 0; } void test_func() { 
      Cert* pCert = new Cert(); memcpy(pCert->m_msg, "2.0.1", MSG_LEN); char *p = new char[10*1024*1024]; } 

makefile

#gcc-4.9.4不支持选项 -fsanitize-recover=all,导致检查到内存错误时程序自动退出 CC= g++ ifeq ($(memcheck), address) CC= gcc-7.5.0 -fsanitize=address -fsanitize-recover=all -static-libasan -fno-omit-frame-pointer -DEnable_AddressSanitizer -DAnalyze_address else ifeq ($(memcheck), thread) CC= gcc-7.5.0 -fsanitize=thread -fsanitize-recover=all -shared -static-libtsan -fno-omit-frame-pointer -DEnable_AddressSanitizer -DAnalyze_thread else ifeq ($(memcheck), leak) CC= gcc-7.5.0 -fsanitize=leak -fsanitize-recover=all -static-liblsan -fno-omit-frame-pointer -DEnable_AddressSanitizer -DAnalyze_leak else ifeq ($(memcheck), undefined) CC= gcc-7.5.0 -fsanitize=undefined -fsanitize-recover=all -fno-omit-frame-pointer -DEnable_AddressSanitizer -DAnalyze_undefined endif #makefile 必须要有标签 all: ${ 
     CC} -g address.cpp -o address -I. -L. -lpthread -fPIC -lstdc++ 

编译脚本 build.sh

#!/bin/bash if [[ ${1} == memcheck=address ]]; then make $1 elif [[ ${1} == memcheck=thread ]]; then make $1 elif [[ ${1} == memcheck=leak ]]; then make $1 elif [[ ${1} == memcheck=undefined ]]; then make $1 else make fi 

编译脚本使用示例:

./build.sh memcheck=address #生成用于检测内存错误的应用程序 ./build.sh memcheck=thread #生成用于检测多线程竞争的应用程序 ./build.sh memcheck=leak #生成用于检测内存泄露的应用程序 ./build.sh memcheck=undefined #生成用于检测未定义操作的应用程序 

3.设置运行环境

上述步骤为编译环境操作,如下是 运行环境的设置。需要设置gcc7.5.0的路径信息:导入gcc7.5.0自带的lib64路径

#若设置用户的环境变量,需执行source命令 export LD_LIBRARY_PATH=/opt/gcc-7.5.0/lib64:$LD_LIBRARY_PATH #告诉address检测到异常不退出进程 export ASAN_OPTIONS=halt_on_error=0 

4.运行程序

# 注:运行环境要有gcc-7.5.0:拷贝gcc-7.5.0.tar 解压至opt目录 ./address 

5.分析内存检测报告

# 运行一段时间后,kill掉进程,程序会自动生成内存检测报告 kill -3 `pidof address` 

内存检测报告:

[root@localhost test_AddressSanitizer]# cat yangyulong_Analyze_address_2021-08-10\ 17_31_42.log ================================================================= ==29819==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000005105c6 at pc 0x00000045b832 bp 0x7ffdf0 sp 0x7ffda0 READ of size 128 at 0x0000005105c6 thread T0 #0 0x45b831 in __interceptor_memcpy ../../.././libsanitizer/asan/asan_interceptors.cc:456 #1 0x4fa7f9 in test_func() /home/debug/test_AddressSanitizer/address.cpp:90 #2 0x4fa788 in main /home/debug/test_AddressSanitizer/address.cpp:80 #3 0x7f5f846a8b34 in __libc_start_main (/lib64/libc.so.6+0x21b34) #4 0x405dcb (/home/debug/test_AddressSanitizer/address+0x405dcb) 0x0000005105c6 is located 0 bytes to the right of global variable '*.LC9' defined in 'address.cpp' (0x5105c0) of size 6 '*.LC9' is ascii string '2.0.1' SUMMARY: AddressSanitizer: global-buffer-overflow ../../.././libsanitizer/asan/asan_interceptors.cc:456 in __interceptor_memcpy Shadow bytes around the buggy address: 0x00008009a060: 01 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9 0x00008009a070: 00 04 f9 f9 f9 f9 f9 f9 00 01 f9 f9 f9 f9 f9 f9 0x00008009a080: 00 00 00 f9 f9 f9 f9 f9 03 f9 f9 f9 f9 f9 f9 f9 0x00008009a090: 00 00 00 00 00 00 00 00 00 05 f9 f9 f9 f9 f9 f9 0x00008009a0a0: 00 00 f9 f9 f9 f9 f9 f9 00 00 00 06 f9 f9 f9 f9 =>0x00008009a0b0: 00 00 07 f9 f9 f9 f9 f9[06]f9 f9 f9 f9 f9 f9 f9 0x00008009a0c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00008009a0d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00008009a0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00008009a0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x00008009a100: 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 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 ================================================================= ==29819==ERROR: LeakSanitizer: detected memory leaks Direct leak of  byte(s) in 7 object(s) allocated from: #0 0x4c0610 in operator new[](unsigned long) ../../.././libsanitizer/asan/asan_new_delete.cc:82 #1 0x4fa803 in test_func() /home/debug/test_AddressSanitizer/address.cpp:92 #2 0x4fa788 in main /home/debug/test_AddressSanitizer/address.cpp:80 #3 0x7f5f846a8b34 in __libc_start_main (/lib64/libc.so.6+0x21b34) Direct leak of 96 byte(s) in 6 object(s) allocated from: #0 0x4c0470 in operator new(unsigned long) ../../.././libsanitizer/asan/asan_new_delete.cc:80 #1 0x4fa7a9 in test_func() /home/debug/test_AddressSanitizer/address.cpp:89 #2 0x4fa788 in main /home/debug/test_AddressSanitizer/address.cpp:80 #3 0x7f5f846a8b34 in __libc_start_main (/lib64/libc.so.6+0x21b34) Indirect leak of 774 byte(s) in 6 object(s) allocated from: #0 0x4c0610 in operator new[](unsigned long) ../../.././libsanitizer/asan/asan_new_delete.cc:82 #1 0x4fa8ba in Cert::Cert() /home/debug/test_AddressSanitizer/address.h:13 #2 0x4fa7b4 in test_func() /home/debug/test_AddressSanitizer/address.cpp:89 #3 0x4fa788 in main /home/debug/test_AddressSanitizer/address.cpp:80 #4 0x7f5f846a8b34 in __libc_start_main (/lib64/libc.so.6+0x21b34) SUMMARY: AddressSanitizer:  byte(s) leaked in 19 allocation(s). 

检测报告各部分介绍:

  1. ERROR:指出错误类型是global-buffer-overflow
  2. READ:指出线程名thread T0,操作为READ,发生的位置是address.cpp:90
  3. SUMMARY:前面输出的概要说明

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233256.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 一张色环图教你搞定配色![通俗易懂]

    一张色环图教你搞定配色![通俗易懂]一张色环图教你搞定配色!不管是在平面设计或网页制作中,还是在平常生活中的衣服穿搭和室内装潢中,要想打造出非凡的视觉效果,合理的颜色搭配非常重要。下面介绍几种色彩搭配方案供您参考,让你轻易地一靶中的

    2022年8月5日
    9
  • SSH批量更新getHibernateTemplate().bulkUpdate(hql)

    SSH批量更新getHibernateTemplate().bulkUpdate(hql)当用 getHibernate bulkUpdate hql 这个方法是会报错 org springframew jdbc Uncategorize Hibernateope couldnotexec uncategorize

    2025年10月22日
    3
  • ipfs矿机挖币是骗局(ipfs挖矿用什么网络)

    友情提示:Filecoin还没上线,任何打着Filecoin旗号说现在就能挖矿的都是骗纸!币圈人对挖矿这件事情上心还得要扯到比特币。2012年的时候,阿瓦隆的创始人开发了ASIC芯片,当时ASIC矿机一面世,平均一天可以挖到375枚比特币!你没有看错是375枚!按照当时的比特币价格计算,阿瓦隆一天的挖矿收入就是20万元型态人民币!赚的盆满钵满! 时光一去不复返,如今的比特币挖矿行业竞争已经进入白…

    2022年4月14日
    53
  • wifi reaver

    wifi reaverPIN码的格式很简单,八位十进制数,最后一位(第8位)为校验位(可根据前7位算出),验证时先检测前4位,如果一致则反馈一个信息,所以只需1万次就可完全扫描一遍前4位,前4位确定下来的话,只需再试1000次(接下来的3位),校验位可通过前7为算出,就可暴力验证出pin码。所以即时你不知道校验位怎么计算,那你最多尝试10000+1000+10次=11010次就可以获得PIN,从而获得wifi…

    2022年6月4日
    46
  • JSON字符串转对象_微信小程序配置文件

    JSON字符串转对象_微信小程序配置文件微信就是最大的坑!!!!!之前做的小程序,前台都是默认参数(返回json之类的),使用也都正常然而,今天发现的问题也是愁死个人,返回的json就是字符串,自然取不到里面的数据.小程序的js还有好多函数他不支持,坑.之前都是returnjson_encode($arr);这样子返回数据,代码都是一样,就这次莫名不好使.网上的答案也是千篇一律.最后有两篇文章都提到了一个问题,一试,果然有效.转jso…

    2022年9月28日
    5
  • 申请软件著作权步骤_著作权包括哪些

    申请软件著作权步骤_著作权包括哪些今年八月底版权中心系统升级,新系统相对好用一些,至少不用再拿IE访问了,但是多了一项实名认证。下面介绍新系统的操作流程。目录注册、登录和实名认证注册登录实名认证软件登记申请申请表填写鉴别材料身份证明文件权利归属证明文件其他材料提交材料变更登记注册、登录和实名认证首先访问版权中心系统:https://register.ccopyright.com.cn/login.html,如果老系统有账号直接登录即可,没有的话需要注册。注册点击注册按钮进入注册。根据实际情况选择个人或单位,每个个人或单位只能在

    2022年9月22日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号