linux 编程----内存泄露检测之Valgrind

本文部分参考网上相关资料。
Valgrind能做什么?
•内存使用检测,包括:
–内存泄漏
–非法内存访问
–未初始化变量使用
–重复释放内存
•多线程竞争
–检测死锁
-检测竞争

Valgrind还能做什么?
•性能分析
–Cachegrind+ cg_annotate

它模拟 CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中 cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数,这些可以看成程序的执行成本。以上数据其实对于app开发意义不大,仅作为参考。

 

转载请注明出处:http://blog.csdn.net/yf210yf/article/details/8023625

1、下载

http://valgrind.org/downloads/current.html

目前最新为valgrind 3.8.1 (tar.bz2) 版本


2、安装

标准gnu软件安装方式,./configure — make — make install
如果安装顺利,valgrind可执行程序已经被安装到/usr/bin下可以直接使用了

完整的说明:

1). Run ./configure, with some options if you wish. The only interesting
one is the usual --prefix=/where/you/want/it/installed.

2). Run "make".

3). Run "make install", possibly as root if the destination permissions
require that. --- Ubuntu下需要root权限,即应该这样运行: sudo make install

4). See if it works. Try "valgrind ls -l". Either this works, or it
bombs out with some complaint. In that case, please let us know
(see
www.valgrind.org).
可能会出现以下的错误:

valgrind: Fatal error at startup: a function redirection
valgrind: which is mandatory for this platform-tool combination
valgrind: cannot be set up. Details of the redirection are:
valgrind:
valgrind: A must-be-redirected function
valgrind: whose name matches the pattern: index
valgrind: in an object with soname matching: ld-linux.so.2
valgrind: was not found whilst processing
valgrind: symbols from the object with soname: ld-linux.so.2
valgrind:
valgrind: Possible fixes: (1, short term): install glibc's debuginfo
valgrind: package on this machine. (2, longer term): ask the packagers
valgrind: for your Linux distribution to please in future ship a non-
valgrind: stripped ld.so (or whatever the dynamic linker .so is called)
valgrind: that exports the above-named function using the standard
valgrind: calling conventions for this platform. The package you need
valgrind: to install for fix (1) is called
valgrind:
valgrind: On Debian, Ubuntu: libc6-dbg
valgrind: On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo
valgrind:
valgrind: Cannot continue -- exiting now. Sorry.

以上错误,是因为在Ubuntu下还需要一个LIB:libc6-dbg

运行:sudo apt-get install libc6-dbg 以安装libc6-dbg

然后再次运行: valgrind ls -l

转载请注明出处:http://blog.csdn.net/yf210yf/article/details/8023625

3、工具

valgrind包含几个标准的工具,它们是:

(1)memcheck

memcheck探测程序中内存管理存在的问题。它检查所有对内存的读/写操作,并截取所有的malloc/new/free/delete调用。因此memcheck工具能够探测到以下问题:

1)使用未初始化的内存

2)读/写已经被释放的内存

3)读/写内存越界

4)读/写不恰当的内存栈空间

5)内存泄漏

6)使用malloc/new/new[]和free/delete/delete[]不匹配。

(2)cachegrind

cachegrind是一个cache剖析器。它模拟执行CPU中的L1, D1和L2 cache,因此它能很精确的指出代码中的cache未命中。如果你需要,它可以打印出cache未命中的次数,内存引用和发生cache未命中的每一行代码,每一个函数,每一个模块和整个程序的摘要。如果你要求更细致的信息,它可以打印出每一行机器码的未命中次数。在x86和amd64上,cachegrind通过CPUID自动探测机器的cache配置,所以在多数情况下它不再需要更多的配置信息了。

(3)helgrind

helgrind查找多线程程序中的竞争数据。helgrind查找内存地址,那些被多于一条线程访问的内存地址,但是没有使用一致的锁就会被查出。这表示这些地址在多线程间访问的时候没有进行同步,很可能会引起很难查找的时序问题。

4、原理

valgrind对你的程序都做了些什么

valgrind被设计成非侵入式的,它直接工作于可执行文件上,因此在检查前不需要重新编译、连接和修改你的程序。要检查一个程序很简单,只需要执行下面的命令就可以了

valgrind --tool=tool_name program_name

比如我们要对ls -l命令做内存检查,只需要执行下面的命令就可以了

valgrind --tool=memcheck ls -l

不管是使用哪个工具,valgrind在开始之前总会先取得对你的程序的控制权,从可执行关联库里读取调试信息。然后在valgrind核心提供的虚拟CPU上运行程序,valgrind会根据选择的工具来处理代码,该工具会向代码中加入检测代码,并把这些代码作为最终代码返回给valgrind核心,最后valgrind核心运行这些代码。

如果要检查内存泄漏,只需要增加--leak-check=yes就可以了,命令如下

valgrind --tool=memcheck --leak-check=yes ls -l

不同工具间加入的代码变化非常的大。在每个作用域的末尾,memcheck加入代码检查每一片内存的访问和进行值计算,代码大小至少增加12倍,运行速度要比平时慢25到50倍。

valgrind模拟程序中的每一条指令执行,因此,检查工具和剖析工具不仅仅是对你的应用程序,还有对共享库,GNU C库,X的客户端库都起作用。

5、使用

首先,在编译程序的时候打开调试模式(gcc编译器的-g选项)。如果没有调试信息,即使最好的valgrind工具也将中能够猜测特定的代码是属于哪一个函数。打开调试选项进行编译后再用valgrind检查,valgrind将会给你的个详细的报告,比如哪一行代码出现了内存泄漏。

当检查的是C++程序的时候,还应该考虑另一个选项 -fno-inline。它使得函数调用链很清晰,这样可以减少你在浏览大型C++程序时的混乱。比如在使用这个选项的时候,用memcheck检查openoffice就很容易。当然,你可能不会做这项工作,但是使用这一选项使得valgrind生成更精确的错误报告和减少混乱。

一些编译优化选项(比如-O2或者更高的优化选项),可能会使得memcheck提交错误的未初始化报告,因此,为了使得valgrind的报告更精确,在编译的时候最好不要使用优化选项。

如果程序是通过脚本启动的,可以修改脚本里启动程序的代码,或者使用--trace-children=yes选项来运行脚本。

测试文件:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
	int *p1=new int;
	int *p2=new int;
	int *p3=(int*)malloc(sizeof(int));
	int *p4=(int*)malloc(sizeof(int));
	int *p5=new int;

	*p1=0;
	*p2=0;
	*p3=0;
	*p4=0;
	p5[10]=0;

	delete p1;
	free(p3);
	return 0;
}   


先编译

$ g++ -Wall -g main.cpp -o main

再用valgrind 测试

$ valgrind --tool=memcheck --leak-check=full ./main

得到

==13925== Memcheck, a memory error detector
==13925== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==13925== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==13925== Command: ./main
==13925==
==13925== Invalid write of size 4 /*数组越界错误*/
==13925== at 0x804864C: main (main.cpp:16)
==13925== Address 0x42f2130 is not stack'd, malloc'd or (recently) free'd
==13925==
==13925==
==13925== HEAP SUMMARY:
==13925== in use at exit: 12 bytes in 3 blocks
==13925== total heap usage: 5 allocs, 2 frees, 20 bytes allocated
==13925==
==13925== 4 bytes in 1 blocks are definitely lost in loss record 1 of 3
==13925== at 0x4029860: operator new(unsigned int) (vg_replace_malloc.c:292)
==13925== by 0x80485E8: main (main.cpp:7) /*new的内存未释放*/
==13925==
==13925== 4 bytes in 1 blocks are definitely lost in loss record 2 of 3
==13925== at 0x4029D56: malloc (vg_replace_malloc.c:270)
==13925== by 0x8048608: main (main.cpp:9) /*malloc的内存未释放*/
==13925==
==13925== 4 bytes in 1 blocks are definitely lost in loss record 3 of 3
==13925== at 0x4029860: operator new(unsigned int) (vg_replace_malloc.c:292)
==13925== by 0x8048618: main (main.cpp:10) /*new的内存未释放*/
==13925==
==13925== LEAK SUMMARY:
==13925== definitely lost: 12 bytes in 3 blocks
==13925== indirectly lost: 0 bytes in 0 blocks
==13925== possibly lost: 0 bytes in 0 blocks
==13925== still reachable: 0 bytes in 0 blocks
==13925== suppressed: 0 bytes in 0 blocks
==13925==
==13925== For counts of detected and suppressed errors, rerun with: -v
==13925== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 17 from 6)

测试效果不错!问题都检测出来了。

转载请注明出处:http://blog.csdn.net/yf210yf/article/details/8023625

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值