使用asan检测内存泄漏、堆栈溢出等问题
创始人
2025-05-29 04:02:56
0

一、使用过程

  • 操作过程参考:链接
  • 缘起:程序在移动端崩溃,mac端复现不了,于是在写个崩溃位置函数的调用demo,使用ASAN工具进行排查。
  • 验证过程
    1、代码
    main.cpp
#include 
#include "opencv2/core/core.hpp"
#include "opencv2/opencv.hpp"template
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(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,wsize_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 
#include 
#include 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:308SUMMARY: AddressSanitizer: 100 byte(s) leaked in 1 allocation(s).

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

有了这么详细的且准确的错误报告,内存问题是不是不那么头疼了?

相关内容

热门资讯

北方华创,巨额商誉压力突然高悬... 文丨詹詹编辑丨百进来源丨新商悟(本文约为 1300字)当国内半导体设备龙头北方华创交出一份“营收创历...
长城华西银行原女掌门已回老东家... 湘财Plus注意到,四川银行入主长城华西银行后,该行核心管理人员调整基本落定,法定代表人已正式变更为...
立案,跌停!这家“童年记忆”,... 沉浮多年,方向何在?最近被立案的上市公司,着实有些多,就在上周末,又有一家上市公司及原董事长被立案调...
加码生态环境监测!生态环境部:... 本文来源:时代周报 作者:李杭4月27日,生态环境部举行4月例行新闻发布会。 生态环境部4月例行新...
东方甄选主播“离职潮”持续发酵... 红星资本局4月27日消息,东方甄选(01797.HK)主播“离职潮”事件仍在发酵。在社交平台上,有部...
SpaceX万亿IPO前夜:马... 从20亿美元收购,到万亿IPO前的最后叙事。2026年4月23日深夜,特斯拉向SEC提交了一份季报文...
前董事长陆宏达“闪电辞职”牵扯... 紧急澄清前董事长性侵指控后,智度股份仍难挡股价大跌。4月27日,智度股份早盘一度重挫逾9%,逼近6....
高盛:一场全球性化工危机正在爆... 霍尔木兹海峡通行受阻,正在引发一场史无前例的全球化工供应冲击。高盛最新报告表示,基础化工品价格近几周...
这笔400亿,谷歌买的不是友谊... 4月25日,Anthropic宣布谷歌将向其投资最高400亿美元——先期注入100亿美元现金,估值3...
粪坑,爬出来了 粪坑,爬出来了... 图:Simon Bailly 读者说:“有人发现吗?2019年蚂蚁的大热基金鹏华快回本了,当年最高回...