使用asan检测内存泄漏、堆栈溢出等问题

这篇具有很好参考价值的文章主要介绍了使用asan检测内存泄漏、堆栈溢出等问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、使用过程

  • 操作过程参考:链接
  • 缘起:程序在移动端崩溃,mac端复现不了,于是在写个崩溃位置函数的调用demo,使用ASAN工具进行排查。
  • 验证过程
    1、代码
    main.cpp
#include <string.h>
#include "opencv2/core/core.hpp"
#include "opencv2/opencv.hpp"

template<typename T>
inline T fastMin(const T a, const T b) {
    return (a < b ? a : b);
}


cv::Mat letterbox(const cv::Mat &src, const cv::Size &target_size, int stride = 32, bool hold_target = true,
                  int resize_func = 0) {
    int ori_w = src.cols;
    int ori_h = src.rows;
    int tar_w = target_size.width;
    int tar_h = target_size.height;

    auto r = fastMin<float>(float(tar_h) / float(ori_h), float(tar_w) / float(ori_w));
    int in_w = int(round(float(ori_w) * r));
    int in_h = int(round(float(ori_h) * r));
    int pad_w = tar_w - in_w;
    int pad_h = tar_h - in_h;
    if (!hold_target) {
        pad_w = pad_w % stride;
        pad_h = pad_h % stride;
    }
    cv::Mat resize_img;
    cv::resize(src, resize_img, cv::Size(in_w, in_h), 0, 0, resize_func);
    float nw = float(pad_w) / 2;
    float nh = float(pad_h) / 2;
    int top = int(round(nh - 0.1));
    int bottom = int(round(nh + 0.1));
    int left = int(round(nw - 0.1));
    int right = int(round(nw + 0.1));
    auto pad_color = cv::Scalar(114, 114, 114);
    cv::copyMakeBorder(resize_img, resize_img, top, bottom, left, right, cv::BORDER_CONSTANT, pad_color);
    return resize_img;
}

void pre_process(unsigned char *image_rgba, cv::Mat &input, int img_height, int img_width) {
    cv::Size target;
    switch (0) {
        case 1:
            target = cv::Size(160,160);//cfg_.MID_DEVICE_INFER_SIZE, cfg_.MID_DEVICE_INFER_SIZE);
            break;
        case 2:
            target = cv::Size(120,120);//cfg_.LOW_DEVICE_INFER_SIZE, cfg_.LOW_DEVICE_INFER_SIZE);
            break;
        default:
            //get model input h,w
            size_t height_ = 320;//detector_helper_->GetInputHeight();
            size_t width_ = 320;//detector_helper_->GetInputWidth();
            target = cv::Size((int) width_, (int) height_);
    }
    bool hold_target = true;//(options_.coreML_mode ||options_.NPU_mode);
    if(hold_target){
        size_t height_ = 320;//detector_helper_->GetInputHeight();
        size_t width_ = 320;//detector_helper_->GetInputWidth();
        target = cv::Size((int) width_, (int) height_);
    }
    cv::Mat image = cv::Mat(img_height, img_width, CV_8UC4, image_rgba);

    input = letterbox(image, target, 32, hold_target,0);
}


int main() {
	
	cv::Mat image_bgr = cv::imread("/root/Downloads/llp.png");
	cv::Mat imgrgba;
	cv::cvtColor(image_bgr, imgrgba, cv::COLOR_BGR2RGBA);
	int width = image_bgr.cols;
	int height = image_bgr.rows;
	cv::Mat input;
	pre_process(imgrgba.data, input, height, width);
	//letterbox(imgrgba, cv::Size(320, 320), 32, true,0);

    return 0;
}

使用附加ASAN工具的方式进行编译:

g++ main.cpp -o detectBug  -fsanitize=leak -g `pkg-config --cflags --libs opencv`

执行:

./detectBug

没有问题,以上是验证过程,如有问题执行时ASAN会提示有问题的相关位置。

二、ASAN资料

  • 介绍

首先,先介绍一下 Sanitizer 项目,该项目是谷歌出品的一个开源项目,该项目包含了 ASAN、LSAN、MSAN、TSAN等内存、线程错误的检测工具,这里简单介绍一下这几个工具的作用:

ASAN: 内存错误检测工具,在编译命令中添加-fsanitize=address启用

LSAN: 内存泄漏检测工具,已经集成到 ASAN 中,可以通过设置环境变量ASAN_OPTIONS=detect_leaks=0来关闭ASAN上的LSAN,也可以使用-fsanitize=leak编译选项代替-fsanitize=address来关闭ASAN的内存错误检测,只开启内存泄漏检查。

MSAN: 对程序中未初始化内存读取的检测工具,可以在编译命令中添加-fsanitize=memory -fPIE -pie启用,还可以添加-fsanitize-memory-track-origins选项来追溯到创建内存的位置

TSAN: 对线程间数据竞争的检测工具,在编译命令中添加-fsanitize=thread启用 其中ASAN就是我们今天要介绍的重头戏。

ASAN,全称 AddressSanitizer,可以用来检测内存问题,例如缓冲区溢出或对悬空指针的非法访问等。

根据谷歌的工程师介绍 ASAN 已经在 chromium 项目上检测出了300多个潜在的未知bug,而且在使用 ASAN 作为内存错误检测工具对程序性能损耗也是及其可观的。

根据检测结果显示可能导致性能降低2倍左右,比Valgrind(官方给的数据大概是降低10-50倍)快了一个数量级。

而且相比于Valgrind只能检查到堆内存的越界访问和悬空指针的访问,ASAN 不仅可以检测到堆内存的越界和悬空指针的访问,还能检测到栈和全局对象的越界访问。

这也是 ASAN 在众多内存检测工具的比较上出类拔萃的重要原因,基本上现在 C/C++ 项目都会使用ASAN来保证产品质量,尤其是大项目中更为需要。

  • 如何使用 ASAN

作为如此强大的神兵利器,自然是不会在程序员的战场上失宠的。

从LLVM3.1、GCC4.8、XCode7.0、MSVC16.9开始ASAN就已经成为众多主流编译器的内置工具了,因此,要在项目中使用ASAN也是十分方便。

现在只需要在编译命令中加上-fsanitize=address检测选项就可以让ASAN在你的项目中大展神通,接下来通过几个例子来看一下 ASAN 到底有哪些本领。

注意:

在下面的例子中打开了调试标志-g,这是因为当发现内存错误时调试符号可以帮助错误报告更准确的告知错误发生位置的堆栈信息,如果错误报告中的堆栈信息看起来不太正确,请尝试使用-fno-omit-frame-pointer来改善堆栈信息的生成情况。
如果构建代码时,编译和链接阶段分开执行,则必须在编译和链接阶段都添加-fsanitize=address选项。

检测内存泄漏

// leak.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[]) {
    char *s = (char*)malloc(100);
    strcpy(s, "Hello world!");
    printf("string is: %s\n", s);
    return 0;
}

上述代码中我们分配了100个字节的内存空间,但在main函数返回前始终没有释放,接下来我们使用ASAN看一下是否能够检测出来,添加-fsanitize=address -g参数构建代码并执行:

~/Code/test$ gcc noleak.c -o noleak -fsanitize=address -g
~/Code/test$ ./leak 
string is: Hello world!

=================================================================
==1621572==ERROR: LeakSanitizer: detected memory leaks    // 1)

Direct leak of 100 byte(s) in 1 object(s) allocated from:   // 2)
    #0 0x7f5b986bc808 in __interceptor_malloc ../../../../src/libsanitizer/ASAN/ASAN_malloc_linux.cc:144
    #1 0x562d866b5225 in main /home/chenbing/Code/test/leak.c:7
    #2 0x7f5b983e1082 in __libc_start_main ../csu/libc-start.c:308

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

这里,ASAN 提供的报告说明了错误原因是detected memory leaks内存泄漏了1),同时,2)说明ASAN检测到应用程序分配了100个字节,并捕获到了内存分配位置的堆栈信息,还告诉了我们内存是在leak.c:7分配的。

有了这么详细的且准确的错误报告,内存问题是不是不那么头疼了?文章来源地址https://www.toymoban.com/news/detail-507359.html

到了这里,关于使用asan检测内存泄漏、堆栈溢出等问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 性能优化-内存泄漏、内存溢出、cpu占用高、死锁、栈溢出详解

    含义:内层泄露是程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费。(换言之,GC回收不了这些不再被使用的对象,这些对象的生命周期太长) 危害:当应用程序长时间连续运行时,会导致严重的性能下降;OOM;偶尔会耗尽连接对象;可

    2024年01月19日
    浏览(56)
  • Java中的内存溢出与内存泄漏深度解析

    目录 引言 一. 内存溢出(Memory Overflow) 1.1 堆内存溢出 1.2 栈内存溢出 1.3 内存溢出的解决策略 1.3.1 优化对象的创建和销毁 1.3.2 调整堆内存大小 1.3.3  使用内存分析工具 1.3.4 避免创建过大的对象 1.3.5 定期清理不再使用的对象 二、 内存泄漏(Memory Leak) 2.1Java内存泄漏的典

    2024年02月19日
    浏览(44)
  • 前端内存泄漏和溢出的情况以及解决办法

    在平时写代码时,内存泄漏的情况会时有发生,虽然js有内存回收机制,但在平时编程中还是需要注意避免内存泄漏的情况;前几天做移动端时遇到一个内存泄漏造成移动端页面卡顿的问题,所以想总结下前端内存泄漏的情况,回顾下基础知识  程序运行时操作系统会分配相

    2024年01月19日
    浏览(39)
  • Android TextView动态地加载资源文件,避免Native 层内存泄漏或内存溢出

    在 Android 中,如果使用 TextView 的 setBackgroundResource() 方法设置背景,可能会导致 Native 层内存增长。这是因为 setBackgroundResource() 方法会将资源文件(例如图片)加载到内存中,如果频繁地调用该方法,就会导致内存泄漏或内存溢出。 为了避免这种问题,可以使用 TextView 的 s

    2024年02月09日
    浏览(29)
  • 使用Visual Leak Detector排查内存泄漏问题

    目录 1、VLD工具概述 2、下载、安装VLD 2.1、下载VLD 2.2、安装VLD 3、VLD安装目录及文件说明

    2024年02月07日
    浏览(28)
  • centos下使用jemalloc解决Mysql内存泄漏问题

    参考: MySQL bug:https://bugs.mysql.com/bug.php?id=83047tdsourcetag=s_pcqq_aiomsg  https://github.com/jemalloc/jemalloc/blob/dev/INSTALL.md (1)ptmalloc 是glibc的内存分配管理 (2)tcmalloc 是google的内存分配管理模块 (3)jemalloc 是BSD的提供的内存分配管理 (可以 使用jemalloc优化Nginx ) 三者jemalloc和tcmall

    2024年02月11日
    浏览(32)
  • 记1次生产环境java进程内存泄漏问题定位(使用Arthas)

    简介 | arthas, Alibaba 开源的 Java 诊断工具,参照文档安装使用很简单,在线下载或者离线下载后解压运行,启动arthas-boot.jar,会自动扫描jps进程,根据序号选择后进入arthas界面: 常用的是dashboard,thread命令,dashboard命令能扫面当前java进程的全局信息,包括堆栈和线程信息,

    2024年02月22日
    浏览(37)
  • C++内存泄漏检测工具

    在程序中增加相应的内存检测工具  #define CRTDBG MAP ALLOC #include stdlib.h #include crtdbg.h #ifdef DEBUG #ifndef DBGNEW #define DBG_NEW new (_NORMAL_BLOCK,_FILE_LINE_) #define new DBG NEW #endif #endif _CrtDumpMemoryLeaks(); 当没有释放内存时候: 增加了delete时候:  

    2024年01月25日
    浏览(74)
  • 内存泄漏检测方式

    一 、 日志记录         通过宏定义重载了 malloc 和 free 函数,以在分配和释放内存的时候记录一些信息,包括文件名和行号,并将这些信息写入到相应的文件中。然后在 main 函数中演示了使用这些宏进行内存分配和释放。 _malloc 函数: 在分配内存之后,创建一个文件名,

    2024年01月17日
    浏览(29)
  • LeakCanary内存泄漏检测框架分析。

    一、什么叫内存泄漏、内存溢出? 内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个10M的Bitmap,但系统分配给APP的连续内存不足10M,就会导致内存溢出。 内存泄漏(memory leak):是指程序在申请内存后,无法释放已申

    2024年02月15日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包