内存只增不减(非内存泄露)解决

36 篇文章 32 订阅
13 篇文章 0 订阅

内存只增不减(非内存泄露)解决

微信公众号:幼儿园的学霸
个人的学习笔记,关于OpenCV,关于机器学习, …。问题或建议,请公众号留言;

在ADAS项目中,代码中加入了跟踪模块,使得程序的内存占用不断上升,但是却不是内存泄漏,断断续续经过近2周的排查,终于将问题解决,特此记录,希望对你有所帮助!

目录

缘起

在ADAS项目中,由于障碍物检测不是很稳定,某些时刻会出现“跳帧”现象,导致检测的目标框给人一种“一闪一闪”的感觉,因此考虑加入多目标跟踪,以弥补目标检测的不足。多目标跟踪代码是基于OpenCV的目标跟踪模块编写而成,加入之后发现程序的运行内存不断上升,大概4000帧视频,在我的电脑上内存可以从7.3%上升的23%左右,由于跟踪模块的实现均采用的智能指针,加上对代码的自信,因此我认为绝对不可能是内存泄露,但是内存上升的事实摆在这里,无法避免。没办法啦,采用valgrind进行校验,未发现泄露。but,这样也不能解决内存上升的问题啊。so,开始了一遍一遍核对代码,甚至对跟踪代码进行了一遍又一遍的重写,但是问题依然无法解决,这玩意儿折磨了我快2周的时间,真是心累啊。

期间怀疑过是内存碎片的原因,但是当时对内存碎片没有了解,没有深入研究,所以放过了这个提前解决问题的机会(主要是当时不太认为内存碎片不会造成内存增长)。

解决

曙光

经过一遍一遍的折磨,准备放弃时,我感觉需要重新搜索一下内存碎片,终于发现了下面这段话:

glibc的malloc分配的内存在free之后,并不一定会交还给操作系统,释放的内存会被glibc管理维护,方便下次malloc的时候继续使用。是有满足一定的条件的情况下,释放的内存才会交还给操作系统。在不断的malloc,free之后,某一进程会导致大量的内存碎片产生,这些内存碎片由于glibc的回收机制,很难被交还给操作系统。因而出现“内存泄漏”现象。来源:https://blog.csdn.net/Abrahampan/article/details/51601680

山重水复疑无路,柳暗花明又一村,非常感谢上面的作者,他的这句话给了我启发啊,解决了折磨我这么久的问题啊。

搞定

按照提示,安装tcmalloc,过程小记:
1.安装libunwind
http://download.savannah.gnu.org/releases/libunwind下载libunwind-1.3.1.tar.gz解压,

cd libunwind-1.3.1/
./configure #默认安装到/usr/local/lib
#or./configure  --prefix=安装路径
make
sudo make install

2.安装gperftools
https://github.com/gperftools/gperftools/releases/下载gperftools-2.7.tar.gz解压

cd gperftools-2.7/
./configure #默认安装到/usr/local/lib
#or./configure  --prefix=安装路径,如/usr/local/lib/tcmaloc
make
sudo make install

3.配置以使生效
默认安装时,上述文件安装在/usr/local/lib路径下,那么执行命令sudo /sbin/ldconfig即可使库生效;
如果安装路径被人为指定,不在默认路径时,那么需要采用下面两行命令

echo "/usr/local/lib/tcmaloc(代表上面的安装路径)" > /etc/ld.so.conf.d/usr_local_lib.conf
sudo /sbin/ldconfig

4.使用:
1)将tcmalloc通过“-ltcmalloc”链接器标志接入你的应用;
2)通过使用LD_PRELOAD在不是你自己编译的应用中使用tcmalloc,例如,对于我的ADAS程序,我可以按照如下命令执行:

export LD_PRELOAD=/usr/local/lib/libtcmalloc.so
./ADAS_usbCamera -ad ../configfile/usb_4mm_HD_CameraConfig.yaml 

通过该方式执行下,程序内存占用如图:
tcmalloc下内存占用
使用前程序内存占用:
glibc下的malloc内存占用

实验结果证明,使用tcmalloc后程序不再像以前那样内存只增不减

5.其他
通过参考链接中的资料可以发现,在代码的起始位置加入下面2行代码,也可以控制内存占用

mallopt(M_MMAP_MAX, 0); // 禁止malloc调用mmap分配内存
mallopt(M_TRIM_THRESHOLD, 0); // 禁止内存缩进,sbrk申请的内存释放后不会归还给操作系统

//头文件
//#include <malloc.h>

但是在我的实验中,发现内存任然上升,只是上升的速度降下来了,可能还需要其他方法配合吧(如malloc_trim(0),考虑在每一帧图像处理时,首先执行该函数一遍,实测该方法非常影响程序性能,建议慎用)。

总结

1.malloc()/free()作为C标准,ANSI C并没有指定它们具体应该如何实现。各个平台上(windows, mac, linux等等),调用这两个函数时,实现不一样;
2.不要盲目相信glibc, 它虽然是系统默认的,却不一定就好。glibc和stl搭档可能有问题
3.在linux下,malloc()/free()的实现是由glibc库负责的。STL的内存释放,有时候并没有直接返还给os,只是返还给了分配器;
4.针对大量数据,谨慎大量使用STL局部变量,虽然栈上分配的,但它维护的队列是分配在heap上的,它操作的内存不一定能够即使释放,可能产生碎片;
5.对于在堆上申请内存,是会产生一定代价的,特别是滥用,后果也是比较严重的。内存碎片是需要关注的问题。

代码都会写,如何写出高性能,高质量的代码,这玩意而真就是个技术活。

参考

  1. "內存碎片"疑似“内存泄漏”
  2. 几种malloc实现原理 ptmalloc(glibc) && tcmalloc(google) && jemalloc(facebook)
  3. Linux glibc 的 mallopt 海量小内存回收问题
  4. Linux Debugging (九) 一次生产环境下的“内存泄露”
  5. TCMalloc:线程缓冲的Malloc
  6. cmake:动态链接库(so)中静态链接tcmalloc(gperftools2.4)暨静态链接libstdc++
  7. Linux Allocator Does Not Release Small Chunks of Memory


下面的是我的公众号二维码图片,欢迎关注。
图注:幼儿园的学霸

  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值