以史为鉴参考,最终valgrind主旨运行那些代码

多年来,在对于系统开展品质测试,揭示一些难点。在固化进程中品尝选取部分工具,有效的帮带识别难点,并且解决了难点。由于难点相比出色,分享给我们,以便大家遭遇类似题材时,借鉴参考。

一. 简述valgrind是何许,为什么能举行内存走漏

valgrind是一个程序调试及质量分析的工具集,涵盖memcheck,
cachegrind,helgrind,callgrind,启动valgrind时经过–tool来指定具体要调用的工具。不论采取哪个工具,通过valgrind来启动程序时都会收获对程序的控制权,从关联库中读取调试音讯。然后在valgrind要旨提供的杜撰CPU上运行程序,按照选拔的工具处理代码,该工具会向代码中植入检测代码,并把这么些代码作为最终代码重回给valgrind大旨,最终valgrind要旨运行这么些代码。

俺们最常用valgrind进行内存败露检查,通过–tool = memcheck
–leak-check=yes
点名。需求专注的是,memcheck会出席代码检查每一片内存的拜访和进展值运算,导致全部代码大小至少扩充12倍,运行速度比常常慢25-50倍,所以运用valgrind时,保险机器环境有丰富多的内存,倘使经过本身启动内存有十几G,那用valgrind启动程序时,一般启动越发慢,可能1h才能启动程序。或者,valgrind根本就拉不起来程序,此时,须求修改程序的相干安顿参数,想方法将次第启动的经过内存减小。

工具介绍


二.编译程序时的令人瞩目

  1. 编译时,打开调试形式(gcc编译器的-g选项)。

2.
编译时,关闭编译优化选项。一些编译优化增选(比如-O2依然更高的优化增选),可能会使得memcheck提交错误的未开头化报告,由此,为了使得valgrind的告知更确切,在编译的时候最好不要拔取优化选项。

3.
即使程序有对tcmalloc编译看重的话,需求将tcmalloc从编译着重中去掉,否则valgrind扫描可能会井蛙之见一些报警新闻。

  1. 当检查的是C++程序的时候,还相应考虑另一个拔取-fno-inline。它使得函数调用链很清楚,那样可以减小你在浏览大型C++程序时的糊涂。比如在行使这一个选项的时候,用memcheck检查openoffice就很简单。当然,你恐怕不会做那项工作,不过使用这一选项使得valgrind生成更确切的错误报告和压缩混乱。

1 Valgrind

Valgrind是一套Linux下,开放源代码(GPL
V2)的虚假调试工具的联谊。Valgrind由基础(core)以及根据内核的其余调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供劳动给其它工具;而其余工具则接近于插件
(plug-in),利用内核提供的劳动做到种种特定的内存调试义务。

valgrind的结构图

中间:Memcheck。那是valgrind应用最普遍的工具,一个重量级的内存检查器,可以发现开发中多数内存不当使用景况,比如:使用未初叶化的内存,使用已经放出了的内存,内存访问越界等

三. valgrind下载 & 安装

—>
下载:wget http://www.valgrind.org/downloads/valgrind-3.8.1.tar.bz2

当前风行的版本是:Release 3.12.0 20 October 2016

—> 解压:bzip2 -d valgrind-3.8.1.tar.bz2; tar -xvf
valgrind-3.8.1.tar

—> 安装: cd valgrind-3.8.1; ./configure
–prefix=/home/work/tools/valgrind-3.8.1.install;make;make install

安装好后在valgrind-3.8.1.install目录里有: bin, lib, include, share
4个子目录

—> 确认是还是不是安装正确:valgrind –version

—> 编辑/etc/profile,将valgrind工具进入PATH,再source
/etc/profile,那样每一遍使用时都是新装置的valgrind

2. Heap Checker

google-perftools 是一款针对 C/C++ 程序的品质分析工具,它是一个遵守 BSD
协议的开源项目。提供多个工具:包蕴tcmalloc,heap-profiler,
heap-checker,CPU
profiler。heap-checker专门检测内存泄漏,heap-profiler则是内存监控器,可以随时精晓当前内存使用意况(程序中内存使用热点),当然也能检测内存泄漏。

四、valgrind memcheck选项

参见手册http://www.valgrind.org/docs/manual/mc-manual.html

valgrind的选项极度的多,可以参照翻译手册中的表达举行选取,上边列出多少个相比常用的:

Option :–leak-check=no|summary|full|yes  [default summary]

Purpose :
当那一个选项打开时,会当客户程序截止时寻找内存走漏。若是设置为summary,Valgrind会报告有微微内存泄露暴发了。倘使设置为full或yes,Valgrind给出每一个独门的透漏的详细音信。

Option :–leak-resolution=high|med|low  [default low]

Purpose
:在做内存泄漏检查时,确定memcheck将怎么着考虑分化的栈是相同的气象。当设置为low时,只须求前两层栈匹配就觉着是一样的图景;当设置为med,必要求四层栈匹配,当设置为high时,所有层次的栈都必须合营。

注意–leak-resolution=
设置并不影响memcheck查找内存泄漏的力量。它只是改变了结果什么输出。

Option: –show-reachable=yes|no  [default no]

Purpose :
当这几个选项关闭时,内存败露检测器只突显没有指针指向的内存块,或者只好找到指向块中间的指针。当那个选项打开时,内存败露检测器还告知有指针指向的内存块。这几个块是最有可能出现内存败露的地方。你的主次可能,至少在条件上,应该在脱离前释放这几个内存块。那个有指针指向的内存块和没有指针指向的内存块,或者唯有其中指针指向的块,都可能暴发内存败露,因为实在没有一个针对性块初阶的指针能够拿来释放,即便你想去释放它。

Option: -v

Purpose :
突显详细音信。在各类方面突显你的次序的附加音讯,例如:共享对象加载,使用的重置,执行引擎和工具的历程,非凡表现的警示新闻。重复那些标记可以扩张详细的级别。

Option : -fno-inline

Purpose :
当检查的是C++程序的时候,可考虑这几个选项-fno-inline。它使得函数调用链很清晰

Option : –max-stackframe=[default: 2000000]

Purpose :
栈的最大值,默许2000000。假设栈指针的晃动当先这几个数目,valgrind则会以为程序是切换来了其它一个栈执行。

3. getrusage

linux提供rusage结构,可以描述业务进程内存使用处境,类似ps aux。

五. 内存败露扫描进程

—>
程序启动(如若程序本身内存十多少个G,启动分外慢,可能1h多才启动):

 nohup valgrind–tool=memcheck –leak-check=full
–show-reachable=yes

–max-stackframe=8000000 –log-file=./valgrind.log [先后启动命令]
&

—> 判断程序是或不是启动成功:

查找程序端口是不是被监听来判定程序是或不是被valgrind拉起

netstat -anlp|grep 9600|grep LISTEN  
##设若经过名是valgrind,则意味程序已经在valgrind环境中启动成功。

—> 给程序放一些呼吁,请求尽可能覆盖到程序的顺序分支

—>
程序优雅退出,不要让服务在valgrind环境里core掉了。尽量服务有捕获kill信号能力,一般kill
-9 pid会导致服务core掉。

—>
退出等待个几分钟,让valgrind收集退出音讯输出到valgrind.log。最后分析valgrind.log

动用工具定位解决内存难点


八个优异难题,处理进程如下:

六. valgrind.log 报告分析

见手册http://www.valgrind.org/docs/manual/mc-manual.html
,关切关怀definitely lost和possible lost处可能的内存走漏。

1)首先搜关键字『LEAK SUMMARY』,看『definitely
lost』对应是还是不是有值,即使不为0,肯定有内存败露。

2)借使有内存走漏,往上搜报告中『definitely lost in
loss』的报警处,对照程序代码一一排查。

3)常见内存走漏警示

—> a. Illegal read / Illegal write errors

已放出后的内存进行读/写或数组的越界访问等,valgrind报告先后在品味读写不合规内存,造成的结局是程序易发生segmentation
fault(吐core)风险。

Invalid write of size X,访问超出了限制的内存,试图从该内存读取多少

—> b. Use of uninitialised values

检测接纳未伊始化变量,能够检测在尺度判断语句中选择未伊始化变量,因而相应养成在宣称变量时就举行开头化的习惯

Conditional jump or move depends on uninitialised value(s)

—> c. When a heap block is freed with an inappropriate deallocation
function

选取不正确的主意释放内存,比如new/delete ,
malloc/free使用混淆了,new分配的地点用free释放了

Mismatched free() / delete / delete []

—> d. Illegal frees

双重内存释放,比如2次应用free释放同一块内存

Invalid free() / delete / delete[]

澳门永利平台,—> e. Overlapping source and destination blocks

本着C语言常见的memcpy, strcpy, strncpy, strcat,
strncat拷贝类函数,出现源串和目标串地址重叠

Source and destination overlap in memcpy(0xbffff294, 0xbffff280, 21)

—> f. Fishy argument values

所有内存分配类函数在分配内存时,都会传来一个内存分配大小的数,即使您传入的数领先机器所能分配的最大数时,如64位机器上,你传入的size大于了2**63

Argument ‘size’ of function malloc has a fishy (possibly negative)
value: -3

—> g. Leak detecion

HEAP SUMMARY:  

即使指定–show-reachable=yes,在先后退出时memcheck会收集reachable and
indirectly lost blocks

LEAK SUMMARY:

memcheck会记录由malloc/new等函数创制的具有的heap
blocks,因而在程序退出时,memcheck可以领略什么block没有free。如下:

definitely lost: 4 bytes in 1 blocks

indirectly lost: 0 bytes in 0 blocks

possibly lost: 0 bytes in 0 blocks

still reachable: 95 bytes in 6 blocks

definitely
lost:倘使一个block在先后在脱离后,memcheck找不到指向它的pointer,一般是由于在代码中对该block没有free造成的,要紧要关怀。

possibly lost:在程序退出时,memcheck发现仍有 interior
pointer(若是一个pointer指向一个block的高中级某个地点)指向一个block,那么该block被认为是possibly
lost。

still reachable:即使memcheck发现仍有start
pointer指向一个block,那么该block就是still reachable。

4)valgrind无法意识到哪些不当?

valgrind不对静态数组(分配在栈上)举行边界检查。假诺在程序中宣称了一个数组:

int main()

{

char x[10];

x[11] = ´a´;

}

valgrind则不会警告你,出于测试目的,你可以把数组改为动态在堆上分配的数组,那样就可能开展边界检查了。那个办法好像有点小题大做的感觉到。

1. new expression导致的内存泄漏

七. 安装或应用中踩得种种坑

1)valgrind: failed to start tool ‘memcheck’ for platform
‘amd64-linux’

解决办法:

该错误是valgrind启动时,无法找到相关工具文件,有可能是设置好后有关lib的path未设置,也有可能是一起初安装就有标题。解决办法如下:

假定已经设置成功,试一下导出VALGRIND_LIB路径,用法如下(倘使valgrind已经被设置到/home/work/tools/valgrind目录):##亲测有效##

export VALGRIND_LIB=/home/work/tools/valgrind3.8.1/lib/valgrind

2)valgrind –version报错

valgrind: mmap((nil), 134512640) failed during startup.

valgrind: is there a hard virtual memory limit set?

解决办法:

见下,版本太老,里边有bug,重新安装一下较新本子应该能缓解。https://twiki.cern.ch/twiki/bin/view/LHCb/CodeAnalysisTools

澳门永利平台 1

3)vg_alloc_ThreadState: no free slots available

Increase VG_N_THREADS, rebuild and try again.

valgrind: the ‘impossible’ happened:

VG_N_THREADS is too low

解决办法:

a)
修改VG_N_THREADS和NTHREADS的值,安装用的是3.8.1本子,默许VG_N_THREADS是500,现在改为5000,同时NTHREADS由498改成4998。

include/pub_tool_threadstate.h: #define VG_N_THREADS 5000

./memcheck/tests/err_disable4.c: #define NTHREADS 4998  //
VG_N_THREADS – 2

b) 根据1拓展重新安装。

4) Valgrind: FATAL: VG_N_SEGMENTS is too low.

解决办法:

VG_N_SEGMENTS默认是5000。修改coregrind/m_aspacemgr/aspacemgr-linux.c:
VG_N_SEGMENTS从5000改到50000,VG_N_NAME从1000改到5000。

根据1开展重新安装。

5)valgrind.log报告中,在definitely
lost的代码处全是?????全写花了,看不出具体走漏的是在哪一行代码

解决办法:

添加-g,打开调试音信重新编译程序;

valgrind扫描时累加–show-reachable=yes

参考:

1.
http://www.xlgps.com/article/216977.html

  1. 什么行使Valgrind
    memcheck工具进行C/C++的内存泄漏检测

3. 用Valgrind查找内存泄漏和无效内存访问

4. valgrind介绍

1.1 难点讲述

从性质测试时,计算主机可用内存裁减,鲜明存在内存泄漏。

图2-1 12分钟主机内存变化景况

1.2 难点定义分析

在品质测试主机安装Valgrind来展开内存泄漏分析。利用Valgrind启动程序:

valgrind –tool=memcheck –leak-check=full –show-leak-kinds=all
–trace-children=yes ZSmartOCPro IN 2>&1| tee ZSmartOCPro_IN.txt

发送业务音信,然后退出工作进度,能够转移分析文件。

图2-2 五个业务包内存统计摘要

图2-3 九个业务包内存统计摘要

图2-4 可能品质走漏点

从相比较数据看,肯定存在内存泄漏。在作业代码中,为了进步品质,设计上行使new
expression(参考:http://en.cppreference.com/w/cpp/language/new)内存情势,即将使用内存管理起来,重复使用,裁减频仍申请内存,从而夯实品质。

图2-5 new expression

DataNode管理的数目和其自己都是应用那种办法。理论上次内存不存在释放,也不应有有败露。从剖析日志来看,因为DataNode中存在map和vector中内存没有难倒。map和vector的内所有stl自行保管,在DataNode对应的Clear函数,增添map和vector的clear调用,来释放内存。测试时发现,那样的修改并不曾用,why?
map和vector的内存形式也是new
expression方式,clear只是清理计数器,并不曾滑坡size。只有在容器析构的时候,才会释放内存。
修改的方式:在调用DataNode的Clear方法的地点改为显示调用他的析构函数~DataNode()情势来析构其里面的map和vector成员。

1.3 测试评释

图2-6 12分钟内存变化曲线

对照前边曲线,收缩满了一些,表达修改有效。是或不是留存任何内存泄漏景况,使用Valgrind继续进行测试。

图2-7 3个信息的透漏分析汇总

图2-8 12个音讯的泄漏分析汇总

因为第三方库使用难点,存在内存泄漏,不过并其并不曾发生变化。分析其出口其余内存新闻,也未曾疑惑的地点,难题的彻底解决陷入迷茫。

2 double linked导致单元测试core

2.1 难题讲述

在化解难题1时,曾经付出调用DataNode的Clear方法。在跑单元测试用例时,有少量的代码会core,地方为与修改毫不相关的python调用处:

图2-9 double linked 导致core

2.3 难题一举成功

昔日的经历,double
linked一般都是地下内存读写引起。使用Valgrind是足以检查出,确实DataNode相关的内存确实存在不合规读写。
原先达成形式:DataNode管理类和对应buffermanager都是单例的,并且通过静态变量,而其析构不受程序员控制,其内存又有关联系统导致。
修改:DataNode管理类保持单例不变,buffermanager修改为DataNode管理类的分子,由其负责buffer的生命周期。
修改后,运行单元测试正常,难题化解。

3 内存难题终极定位

3.1 难题讲述

如图2-6所示,在缓解了内存泄漏之后,内存仍然收缩而且不能用valgrind检测,是干吗呢?

3.2 难点浅析

valgrind的走漏是检测从起步到退出,检测出无主内存泄漏情状。而且选择Valgrind运行工作程序,程序存在很要紧的卡顿,不相符长日子和大度压力运行。从分析来看,业务经过在运行进度中,可能存在不断申请内存,在剥离进程中释放。例如map或者vector等容器。
初叶探索:

  • 1
    也尝试用getrusage来测试成内存,能窥见内存变大,却无力回天稳定地点。getrusage展现maxrss是以块格局体现。
getrusage测试
  • 2 走查疑心代码。因为代码量大,无目的的走查是很没用的。
  • 3
    利用二分法屏蔽组件方式来压缩范围后,在走查。屏蔽代码可能导致工作不通,未必能找出标题。
    急需另辟蹊径,有同事推荐gperftools来一试。

3.3 难题解决

google-perftools提供heap_checker功能(https://gperftools.github.io/gperftools/heap\_checker.html)。

  • 1 首先是安装gperftools。
  • 2 重新编译业务代码添加 -ltcmalloc 链接tcmalloc库。
  • 3 启动平台,因为经过须要单独启动。

env HEAPCHECK=normal HEAP_PROFILE_ALLOCATION_INTERVAL=104857600
HEAPPROFILE=”/home/hunter/log/test.log” ZSmartOCPro IN

声明:HEAPPROFILE指定生成dump文件的义务;HEAP_PROFILE_ALLOCATION_INTERVAL,程序内存每增加这一数值之后就dump
一回内存,默许是1G, 104857600=100M

内存dump文件

  • 4 利用pprof来分析内存文件

/usr/local/bin/pprof –text –base=/home/hunter/log/test.log.0003.heap
/home/hunter/bin/ZSmartOCPro /home/hunter/log/test.log.0009.heap

内存差别

快快定位出难题所在,和猜疑一直。业务代码写进程漏了调用vector的复位,导致直接坚实。

修改难题后再一次测试后,发现解决内存差距难题。

/home/hunter/log>/usr/local/bin/pprof –text
–base=/home/hunter/log/test.log.0020.heap
/home/hunter/bin/ZSmartOCPro /home/hunter/log/test.log.0055.heap
Using local file /home/hunter/bin/ZSmartOCPro.
Using local file /home/hunter/log/test.log.0055.heap.
Total: -0.0 MB
0.0 -272.7% -272.7% 0.0 -272.7%
std::_Vector_base::_M_create_storage (inline)
0.0 -218.2% -490.9% 0.0 -218.2% Json::Value::Value
0.0 -109.1% -600.0% 0.0 -109.1% TariffTemplate::Instance (inline)
0.0 -109.1% -709.1% 0.0 -109.1% list_resize (inline)
0.0 -109.1% -818.2% 0.0 -109.1% std::vector::push_back (inline)
0.0 -4.5% -822.7% 0.0 -4.5%
std::__cxx11::basic_string::_M_mutate
0.0 -4.5% -827.3% 0.0 -4.5% zmq::msg_t::init_size
0.0 -0.0% -827.3% -0.0 109.1% AcmManager::Initialize
0.0 -0.0% -827.3% 0.0 -109.1% AcmManager::RetrieveAccumulation
0.0 -0.0% -827.3% 0.0 -109.1% AcmManager::RetrieveDataFromTableAcm

至此,难点彻底解决。

小结

因为工具完毕原理的异样,在缓解难点时也各有专长:

  • Valgrind:适合解决不合规读写,无主内存走漏等题材一定。
  • gperftools:长时间运行进程内存使用量应该是政通人和的,gperftools适合发现运行进度中内存差距,提供败露的函数范围。而且对影响影响小,适合高压力急速复现。
  • getrusage:尽管对于定位难点协理不大,可是可以用于守护进程监控管理作业经过的内存使用情形。
    以上是行使工具解决难点的经过,供就学和参照。感谢同事帮助一起定位息争决。