Valgrind原理和检测S++插件内存泄漏的实例方法
来源:互联网 发布:行业大数据平台 编辑:程序博客网 时间:2024/06/08 19:27
0、背景
前几天用valgrind解决了一个台server的内存泄漏(图片上传到存储平)的问题,下面是valgrind的原理和使用方法,感兴趣的同学可以看一下,希望对大家有帮助。J
1、介绍
Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。Valgrind这个名字取自北欧神话中英灵殿的入口。Valgrind的最初作者是Julian Seward,他于2006年由于在开发Valgrind上的工作获得了第二届Google-O'Reilly开源代码奖。你可以在它的环境中运行你的程序来监视内存的使用情况,比如C语言中的malloc和free或者C++中的new和delete。如果你使用了未初始化内存,在数组末端外设置内存或是忘记释放指针,Valgrind都可以检测出来。
1.1、Valgrind的主要功能
Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。架构如下所示:
下面分别介绍个工具的作用:
(1) Memcheck 工具主要检查下面的程序错误:
使用未初始化的内存 (Use of uninitialised memory)
使用已经释放了的内存 (Reading/writing memory after it has been free’d)
使用超过 malloc分配的内存空间(Reading/writing off the end of malloc’d blocks)
对堆栈的非法访问 (Reading/writing inappropriate areas on the stack)
申请的空间是否有释放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)
(2) Callgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。
Cachegrind模拟 CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中 cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。
(3) Helgrind它主要用来检查多线程程序中出现的竞争问题。Helgrind
寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为”Eraser” 的竞争检测算法,并做了进一步改进,减少了报告错误的次数。
(4) Massif堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。
这里主要使用的是Memcheck,适用于Memcheck工具的相关选项:
1.
-leak-check=no|summary|full 要求对leak给出详细信息? [summary]
2.
-leak-resolution=low|med|high how much bt merging in leak check [low]
3.
-show-reachable=no|yes show reachable blocks in leak check? [no]
1.2、安装valgrind
(1) 下载:http://valgrind.org/
(2) 解压:
tar jvxf valgrind-3.6.0.tar.bz2
(3) 安装:
./configure
make
make install
1.3、Memcheck检测原理
Memcheck 能够检测出内存问题,关键在于其建立了两个全局表。
(1) Valid-Value 表:
对于进程的整个地址空间中的每一个字节(byte),都有与之对应的 8 个 bits;对于 CPU 的每个寄存器,也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。
(2) Valid-Address 表
对于进程整个地址空间中的每一个字节(byte),还有与之对应的 1 个 bit,负责记录该地址是否能够被读写。
检测原理:
* 当要读写内存中某个字节时,首先检查这个字节对应的 A bit。如果该A bit显示该位置是无效位置,memcheck 则报告读写错误。
* 内核(core)类似于一个虚拟的 CPU 环境,这样当内存中的某个字节被加载到真实的 CPU 中时,该字节对应的 V bit 也被加载到虚拟的 CPU 环境中。一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则 memcheck 会检查对应的V bits,如果该值尚未初始化,则会报告使用未初始化内存错误
2、Valgrind实例调试S++插件
2.1 内存泄漏的现象
由下图可以看出机器的内存使用量每天都在上涨,初步判定存在内存泄漏的问题。
2.2 调试步骤
步骤1:用valgrind起SPP的worker程序来检测内存泄漏,命令如下图所示。proxy和ctrl进程无需调试的话只需用./spp_actuploadpic_proxy ../conf/spp_proxy_actuploadpic.xml将proxy启动即可。
这里需要调试的SO需使用 -g选项编译,这样就有可能获得一些信息来直接指出相关的代码行。
启动后valgrind会输出一个启动时的summary检查报告,因为没有请求,并未发现启动worker时存在内存泄漏,如下所示:
步骤2:上一步骤只启动一个worker是为了方便观察和调试,用watch简单观察一下worker(进程号是15758)的内存使用,注意这里VSZ虚拟内存占用是以k为单位的,如果是少量的内存泄漏是看不出来的
步骤3:模拟一个请求给SPP,worker的内存使用量上涨了,初步判断是有内存泄漏的。
步骤4:kill -USR1 15758杀掉valgrind起的worker进程,valgrind会输出汇总的报告,如下所示:
报告内容较多,也存在误报的情况,这里需要特别关注自己编写server的代码,如果公共库和API一般经过测试比较稳定了,泄漏的可能性不大。
Memcheck将内存泄露分为两种,一种是可能的内存泄露(Possibly lost),另外一种是确定的内存泄露(Definitely lost)。Possibly lost 是指仍然存在某个指针能够访问某块内存,但该指针指向的已经不是该内存首地址。Definitely lost 是指已经不能够访问这块内存。需要重点关注Definitely lost的信息。
以最后的一块提示信息为例,说明如下:
==15758== 是worker进程的 ID。
消息“34,389 bytes in 3 blocks are definitely lost in loss record 31 of 33”说明有33k的数据没有释放,是在268行(vg_replace_malloc.c)的new进行分配的,该分配是由server_ctl.cpp文件upload_picture()函数的538行调用的。
步骤5:根据提示找到相应的源代码,找到内存泄漏的地方在538行
其它参考资料:
http://blog.ednchina.com/junjinlee/1772918/message.aspx
- Valgrind原理和检测S++插件内存泄漏的实例方法
- C语言检测内存泄漏方法valgrind
- Valgrind检测内存泄漏
- valgrind检测内存泄漏
- valgrind检测内存泄漏
- Valgrind检测内存泄漏
- 用Valgrind检测内存泄漏
- valgrind内存泄漏检测详解
- Valgrind进行内存泄漏检测
- 使用valgrind进行内存泄漏和非法内存操作检测
- 预防和检测内存泄漏的方法:
- 内存泄漏的防范和检测方法
- 内存调试——valgrind工具对数组访问错误和内存泄漏的检测
- GDI泄漏和内存泄漏 检测方法
- Valgrind 内存调试、内存泄漏检测
- 检测内存泄漏的方法
- Valgrind检测Apache web server内存泄漏
- linux实用技巧:检测内存泄漏工具Valgrind
- 2012.4.9 :csocket Notification Sink 问题解决过程
- iBatis一些非常见用法 .
- Activity的onSaveInstanceState方法
- Eclipse快捷键大全
- SQL Server 孤立用户检测与处理
- Valgrind原理和检测S++插件内存泄漏的实例方法
- 用c语言读取固定大小的raw格式图像并统计灰度值
- 瞬间求解最大连续和
- 对于Webservices的超时问题
- Java中MDI的实现
- 伯克利DB
- Oracle 的NVL
- 第八周实验报告(一)《方案一》用类的重载运算符 +、-、*、/,使之能用于复数的加减乘除
- How to Sign Android APK or Zip Files