参考:http://www.cnblogs.com/sunyubo/archive/2010/05/05/2282170.html
几乎是照抄参考过来的,只不过后面自己调试一下代码。
这里着重讲,有关Valgrind的某些简易用法。更多详尽的使用办法, 能够去访问valgrind主页: http://www.valgrind.org。
Valgrind是Julian Seward所创作的作品, 它是运行于Linux之上的, 一套借助仿真技术的程序调试以及分析工具, 它涵盖一个内核, 一个通过软件合成的CPU, 还有一系列的小工具。
每个工具都可以完成一项任务—调试分析或测试等。
能检测内存泄漏以及内存违例的Valgrind, 还能够针对cache的使用展开分析, 它具备灵活性且十分强大, 是值得让人去入手的。
一、Valgrind概述
它主要有下列几个工具。
1.Memcheck
最为常用的, 用以检测程序里出现的内存问题, 所有针对于内存的读写均会被检测到, 一切对malloc以及free的调用都会被捕获, 故而它能够检测如下问题:
1)对为初始化内存的使用
2)读/写释放后的内存块
3)读/写超出malloc分配的内存块
4)读/写不适当的栈中的内存块
5)内存泄漏,指向一块内存的指针永远丢失
6)进行了不恰当的malloc与free搭配, 或者出现了不合理的new与delete对应。
7)memcpy相关函数中的dst和src指针重叠
2.Callgrind
存在一种与gprof相类似的分析工具, 它对于程序的运行观察更为细致入微, 能够为我们提供更多的信息。它与gprof有所不同, 它在编译源代码的时候不需要额外添加专门的特殊选项, 不过加上调试选项是被推荐的。
Callgrind会收集程序运行之际的某些数据, 进而建立函数调用关系图, 并且能够有选择性地开展cache模拟。于运行结束之时, 它会将分析数据写入一个文件里, callgrind_annotate能够把此文件的内容转化成可读取的形式。
3.Cachegrind
有一款Cache分析器, 它主要模拟CPU里头称得上为一级的缓存I1、DI, 并模拟在逻辑意义可归为二级的缓存, 从而能够做到精确地指出程序里面cache的丢失以及命中情况。
如果存在需求, 它能够为我们给出cache丢失的次数, 提供内存引用之次数, 还会逐一给出每行代码对应产生的指令数, 给出每个函数所产生的指令数, 给出每个模块所产生的指令数直至整个程序产生的指令数, 这对于优化程序而言具备极大的帮助作用。
4.Helgrind
多线程程序里出现的竞争问题, 是供其检测的对象。Helgrind找寻内存中, 存在多个线程访问, 然而却不曾一贯加锁的区域。于这些区域而言, 常常是线程之间出现失去同步的状况, 并且会致使难以被发掘的错误产生。
Helgrind达成了称作“Eraser”的竞争检测算法, 且实施了更进一步的改进, 使得报告错误的次数得以减少。然而, Helgrinf依旧处于实验阶段。
5.Massif
堆栈分析器, 其可测量程序于堆栈里所使用的内存量, 告知我们堆块、堆管理块以及栈的大小。Massif能够协助我们降低内存的使用, 在采用代用虚拟内存的现代系统情形下, 它还能够加快我们程序的运行速度, 并减少程序停留在交换区的几率。
除此之外, lackey以及nulgrind也将会予以提供, lackey属于小型工具, 运用的频率极少, nulgrind仅仅是给开发者呈现出咋样去创建一个工具。
二、使用Valgrind
之前进行了安装, 关于我的那台服务器, 其上已然完成了安装操作, 然而不清楚是否就连所有的linux系统, 都是本身就携带这个有关的事物呢。
命令格式如下:
valgrind
valgtind-options
your-prog
your-prog options
比如:
-h 显示帮助信息
呈现内核版本信息那个是用--version来显示的, (而)我却不清楚为啥不是用-v。
-q 安静的运行,只打印错误信息
-tool=
default:memcheck
最为常用的选项, 其后面跟着工具的名称。倘若将工具名予以省略, 那么默认会运行名为memcheck的程序。
比如下面的程序:
#include
#include
void fun()
{
int *x = malloc(10 * sizeof(int));
x[10] = 0;
}
int main()
{
int i = 99;
fun();
printf("i = %d\n", i);
return 0;
}
存在两个问题:
1)没有free掉申请的资源
2)fun函数里面越界了,x是非法的
下面演示如何使用valgrind中的memcheck:
当进行调用这个操作的时候, 还能够去加上这样的tool, 也就是, $valgrind –tool=memcheck 再连接上./malloc , 有这么一回事。
==28308== 中的28308表示程序运行时的进程号。
内存非法写入大小为4, 这代表着非法写入, 于此情况下, 下面所呈现的是告知给我们错误发生之时的位置所在之处, 其位置处于main之中所调用的那个fun函数里面。
HEAP SUMMARY, 它说明了堆的那种情况, 从中能够看到申请了40个字节, 后面又表述的这种情况是有1个申请, 并且有0个被free。
LEAK SUMMARY: 所讲的同样是堆的泄漏状况, 显著遗失的存在40个字节。
要是main当中的i未曾就行赋值操作, 此处还会存有一些别的错误, 具体情况能够自己去尝试一番。这得运用到实际的项目里才能够更加去理解。
下面就是i没有赋值的错误信息截取了部分:
在此介绍一些别样用法, 我是依照参考来学习的, 至于怎样应用到实际项目里, 还得靠自己领会。
测试下面时,main函数中的i我改为了没有赋值:
1.一旦发生错误, valgrind会自行启动调试器(通常是gdb)。
2.下面来试试callgrind:
能瞧见生成了一个文件(显示在绿色框框那儿)。于callgrind运行你撰写的程序之际, 还能够借助callgrind_control去观测程序是怎样一路执行下来 , 并且它运行时不会受到任何干扰: