valgrind 下载就没一个完整使用方法么

新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 33, 距离下一级还需 167 积分
论坛徽章:0
7908 是什么东西啊?
==7908== Thread 60:
==7908== Invalid write of size 1& && && && && && && && && && && && && && && && && && && && && && && &是不是说772行写错误?
==7908==& & at 0x403594: read_thread (epoll_1.c:772)& && && && && && && && && && && &这行是注释
==7908==& & by 0x36C7A0673C: start_thread (in /lib64/libpthread-2.5.so)
==7908==& & by 0x36C6ED3F6C: clone (in /lib64/libc-2.5.so)
==7908==&&Address 0x37779E56 is 0 bytes after a block of size 46 alloc'd& &
==7908==& & at 0x4A04B32: calloc (vg_replace_malloc.c:279)
==7908==& & by 0x4034AE: read_thread (epoll_1.c:756)& && && && && && && && && && &&&是不是说0x4034AE这个地址在756行有操作?
==7908==& & by 0x36C7A0673C: start_thread (in /lib64/libpthread-2.5.so)
==7908==& & by 0x36C6ED3F6C: clone (in /lib64/libc-2.5.so)
==7908== Syscall param socketcall.sendto(msg) points to unaddressable byte(s)&&这一段和上一段先后顺序是怎样的呢?
==7908==& & at 0x36C7A0DE91: send (in /lib64/libpthread-2.5.so)
==7908==& & by 0x403665: read_thread (epoll_1.c:786)
==7908==& & by 0x36C7A0673C: start_thread (in /lib64/libpthread-2.5.so)
==7908==& & by 0x36C6ED3F6C: clone (in /lib64/libc-2.5.so)
==7908==&&Address 0x37779E56 is 0 bytes after a block of size 46 alloc'd
==7908==& & at 0x4A04B32: calloc (vg_replace_malloc.c:279)
==7908==& & by 0x4034AE: read_thread (epoll_1.c:756)
==7908==& & by 0x36C7A0673C: start_thread (in /lib64/libpthread-2.5.so)
==7908==& & by 0x36C6ED3F6C: clone (in /lib64/libc-2.5.so)
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
巨富豪门, 积分 29573, 距离下一级还需 10427 积分
论坛徽章:4
小富即安, 积分 2118, 距离下一级还需 2882 积分
论坛徽章:0
7908是进程PID,
第一段的意思是,在 read_thread (epoll_1.c:772) 位置处出现一个写越界,
越界的地方是在一个 46 字节到内存块的后面,这个内存块是在 read_thread (epoll_1.c:756)&&这个位置申请出来的。
第二段是另一个错误,跟第一段没关系,时间顺序上是靠后
丰衣足食, 积分 533, 距离下一级还需 467 积分
论坛徽章:1
白手起家, 积分 33, 距离下一级还需 167 积分
论坛徽章:0
还有个问题, 注释 会不会影响 valgrind 报的位置啊, inlcude的文件会不会影响?
因为它说的行是注释啊下次自动登录
现在的位置:
& 综合 & 正文
如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测
字节顺序是令人恶心的一个问题。我想说一下我在这方面难过的经历。这里是关键:
数字与数据
一个很重要的概念就是识别数字与代表数字的数据的区别。
数字是一个抽象的概念,如某物的总和。你拥有十个手指。“十”这个概念不会改变,无论你利用何种形式展现,ten,10,diez(西班牙语),ju(日语),1010(二进制),X(罗马数字)...这些形式都指向同一个概念“十”。
相比而言,数据是一个物理概念,一串存储于计算机中的位与字节。数据没有内在的意义,不同的读取对象赋予其不同的解释。
数据如人类的写作一样,只是简单地书写在纸上。它们可以是字母“IO”,木星的卫星,古希腊女神,或为输入/输出的缩写,亦或为某人的首创,二进制中的数字2(“10”)。数据展现的意义具有无限可能。
关键点在于一份数据可以有多种解释,直到有人明确作者的初衷,该数据的意思才被正确解析。
计算机也面临同样的问题。他们存储数据,非抽象的概念,而是通过一序列的1和0方式进行操作。之后,他们通过读取这些1和0形成的原始数据创建抽象的新概念。基于假设条件,这些1和0具有不同的意义。
为何这些问题会产生呢?那是因为我们没有规定所有的计算机必须使用同一种语言,就如我们人类一样。任何一种计算机需保持内部统一,即可识别其自己的数据,然而其他计算机如何解析该计算的数据并未保证。
把数字存储为数据
庆幸的是,大多数计算机都认可一些基本的数据格式 (但并不总是这样). 这给了我们一个同样的入口点,从而让我们的生活更简单:
我们可以依据这些最基本的协议作为构建单元来传输数据. 如果我们每次存储或读取一个字节,那么在所有计算机上都是可行的.字节的概念在所有计算机中都是一样的 . 计算机也认可你发送给他们的字节的顺序-- 它们认可哪个字节是第一个,第二个,第三个等等. 所以第三十五个字节在所有机器上的解释都是一样的.
那,问题是什么呢?计算机都认可一个字节,对吗?
好吧,对于单字节的数据来说这是没问题的,比如ASCII文本. 然而,很多数据需要使用多个字节来存储,比如整数或者浮点数. 而对于这些字节的存储顺序是没有统一的协议的.
以字节为例子
设想一个包含4个字节的序列,其中的元素分别被命名为W X Y和Z - 我没有将它们命名为A B C D是因为它们是16进制的数字,那样的话可能会引起混淆.所以,每一个字节都代表一个值,而且都是由8位组成。
Byte Name:
Value (hex):
例如, W 是一整个字节, 在16进制中表示为0x12,在二进制中表示为.如果W被解析为数字,么在十进制中是"18"
(顺便说一下, 没有什么要求我们必须把它解释成数字 - 它可以是一个ASCII字符或者别的东西 ).
跟上我了吗? 我们有四个字节W X Y 和Z, 每一个字节都有一个不同的值.
指针是编程中很关键的一部分, 特别是在C语言中. 指针是一个指向内存地址的数字,这个数字的解释是由我们(编程人员)决定的 (the programmer) .
在C语言中, 当你把一个指针映射 (转换)成某种类型 (比如一个char * 或者int *),它将告诉计算机如何解释位于那个地址的数据. 举个例子,让我们定义
void *p = 0; // p is a pointer to an unknown data type
// p is a NULL pointer -- do not dereference
// c is a pointer to a single byte
注意,我们不能根据p获取数据因为我们不知道它的类型. p 可以指向一个数字,一个字母,一个字符串的开始, 你的星座, 一张图片 -- 我们不知道需要读取多少字节,也不知道那里到底有什么.
现在假设我们这样写
c = (char *)p;
啊-- 现在这条语句告诉计算机指向跟p相同的位置, 并且将数据解释成为一个字符 (1 byte).这种情况下, c可以指向内存地址0, 或者字节W.如果我们输出c, 我们将获得W处的值, 也就是十六进制的0x12 (记住W是一个完整的字节).
这个例子不依赖于我们拥有的计算机的类型 -- 另外, 所有的计算机都认同字节这个东西 (在过去可不是这样).
这个例子很有意义,即使对于所有的计算机来说这都一样 -- 如果我们有一个指向单独一个字节的指针 (char *,单个字节), 我们就可以遍历整个内存, 每次读取一个字节. 我们可以检查任何一个内存地址,而计算机的大端还是小端并不影响--每一台计算机都会返回同样的信息.
那,问题在哪儿呢?
当计算机尝试读取多个字节的时候问题就出现了. 一些数据类型包含多个字节,比如长整形或者浮点型数字.一个字节只能表示256个值, 所以能存储0-255.
现在问题来了 - 当你读取多个字节的时候,最大的字节在哪儿?
命名很有意义,对吧? 大端机认为大端在最前面. (顺便说一下,大端 /小端的命名来自格列佛游记,那里面的Lilliputans争论到底是从大的一端打破鸡蛋还是从小段一端. 有时候电脑争论也是同样有意义的 )
再回过来,当只有一个字节的时候,大端还是小端并不重要. 如果只有一个字节,它是你唯一读取的数据,所以只有一种解释它的办法 (因为计算机都认可一个字节代表的值).
现在假设我们的四个字节 (W X Y Z) 在大端机和小端机上以同样的方式存储. 就是说,两台机器上内存地址为0的位置都是W,内存地址为1的位置都是X,以此类推.
我们可以通过记住字节是与机器无关的来制造这样的顺序. 我们可以游走整个内存,每次一个字节,然后设置我们需要的值.这在任何机器上都是行得通的:
// point to location 0 (won't work on a real machine!)
*c = 0x12; // Set W's value
// point to location 1
*c = 0x34; // Set X's value
// repeat for Y and Z; details left to reader
上面的代码在任何机器上都是可行的,而且我们把两台机器都设置了字节,W,X,Y,Z分别位于内存地址0,1,2,3的位置.
现在让我们以多字节数据举一个例子 (终于讲多字节了!). 快速复习: 短整型是一个两个字节的数字, 取值范围为0-65535 (如果是无符号的). 让我们在一个例子中使用它:
short *s; // pointer to a short int (2 bytes)
// point to location 0; *s is the value
所以,s是一个指向短整型的指针,而且现在指向位于0地址的字节(0字节存放了W),如果我们读取s处的值将会发生什么?
记住,两台机器都从s位置开始向前读取内存. 对于0地址和1地址代表这个问题没有任何疑问,对于短整型占两个字节这个问题也没有任何疑问.
但你发现问题了吗? 大端机认为 s = 0x1234 而t小端机认为 s = 0x3412.同样的数据却得到两个不同的数字,这不太会是什么好事情.
另一个例子
让我们使用四个字节的整型为例子来“娱乐”一下:
int *i; // pointer to an int (4 bytes on 32-bit machine)
// points to location zero, so *i is the value there
同样我们也会问:i的值是什么?
同样的数据,不同的结果--不是什么好事. 这里有一个使用上面的数字的互动例子,你可以随意添加你自己的:
关于字节顺序的问题有时候也被称作NUXI问题: UNIX被保存在大端机上在小端机上将显示为NUXI.
假设我们想把4个字节 (U, N, I and X)作为两个短整型存储: UN and IX. 每个字母代表一个字节, 就像上面例子中的WXYZ. 要保存着两个短整型,我们可以这样写:
short *s; // pointer to set shorts
// point to location 0
// store first short: U * 256 + N (fictional code)
// point to next location
// store second short: I * 256 + X
这部分代码并不局限于机器.如果我们在一台机器上存储"UN"然后又把它读出来,结果最好是"UN"!我不关心端的问题,如果我们在一台机器上存储了一个值,当我们读取的时候我们需要能够获取同样的值.
然而,如果我们在内存中一次读取一个字节 (使用我们的char * 伎俩), 顺序就可能发生变化.在大端机上我们看到
Location: 0 1 2 3
这很有意义. U 在 "UN"中是最大的,而且被最先存储.对于IX也是一样: I 是最大的,也被优先存储。
在小端机上我们可以看到
Location: 0 1 2 3
这也是有意义的. "N" 在"UN"中时最小的,所以被先存储. 而且,即使字节在内存中是被”反向“存储的,小端机知道它是小端的,所以当读取数据的时候也会正确的解析他们.另外, 注意,我们可以再任何机器上像x = 0x1234一样指定16进制数.当你写0x1234的时候,小端机知道你的意思,它不会强制你让你自己把值给倒过来(你指定了要写的数字是16进制的,它意识到这个细节,然后再内存中将字节颠倒过来,底层操作).
这种场景就被称作"NUXI" 问题,因为字节顺序UNIX在其他类型的机器上会被解释为NUXI . 另外,只有当你交换数据的时候这才是个问题--每台机器内部是一致的.
不同端机器之间交换数据
计算机是互联的 - 那些一台机器只需要关系读取自己的数据的日子已经不复存在了.大端机和小端机之间需要交流并且相处.他们是如何做的呢?
解决方案1: 使用通用的格式
最简单的方式就是认可同样的格式以达到在网络上传输数据的目的. 标准的网络传输顺序实际上是大端在前, 但有些人觉得小端输了就变得很傲慢...我们暂且把它叫做"网络顺序".
要把数据转化成网络顺序, 计算机需要调用一个方法来转换 (主机-到-网络). 在大端机中,这不需要做任何事情,但现在我们不讨论这个(小端机们可能会很抓狂).
但在传输数据之前进行转换是非常重要的, 即使你是大端机.你的程序对于不同的机器来说可能非常熟悉,但你想让你的代码更灵活(不是吗?).
同样的,也有一个转换方法(网络到主机)被用来从网络读取数据. 你需要用它来保证你能够正确的将来自网络的数据转化成你主机的格式.你需要知道你接收的数据的类型才能正确的解码,转换方法在这里:
htons()--"Host to Network Short"
htonl()--"Host to Network Long"
ntohs()--"Network to Host Short"
ntohl()--"Network to Host Long"
记住:一个字节就是一个字节,与顺序没有关系.
这些方法在进行底层网络编程的时候非常关键, 比如验证IP数据包中的校验和. 如果你不能正确的理解“端”的问题,你的生活将很苦逼 -在这方面需要记住我所讲的. 使用转换方法,并且知道为什么需要使用它们.
解决方案2: 使用字节顺序标记 (BOM)
另一个办法就是在每一组数据前面包含一个魔法数字,比如0xFEFF. I如果你读到了魔法数字为0xFEFF, 那就是说读取的数据跟你的机器采用同样的格式,这样一切就好办了.
如果你读到的魔法数字是0xFFFE (它是反向的), 那就意味着读取的数据与你机器上的数据格式是不同的,你就需要进行转化.
有几点需要注意. 首先, 魔法数字并不是真的具有魔法,但编程人员经常使用这个说法来描述选择的任意一个数字(BOM 可以是不同字节的任意序列). 它被称作字节顺序标记是因为它暗示了数据存储的时候使用的顺序.
其次, BOM增加了所有传输数据的开销.即使你正在传输两个字节的数据,你也需要包含两个字节的BOM.哎哟!
Unicode在存储多字节数据的时候就使用BOM (有一些Unicode字符编码会为每个字符使用两个,三个甚至四个字节). XML默认把数据存储成UTF-8格式从而避免了这个复杂的问题, UTF-8每次存一个字节的Unicode信息.为什么可以这么酷?
(第56次重申) "因为端的问题不会影响单个字节".
另外, 使用BOM也会存在其它问题. 如果你忘记包含BOM了怎么办? 你会假设数据是按照你自己的格式传输的吗?你会读取数据并且检查是否它看起来是”反向“(管它什么意思呢)的,然后将它进行转化吗? 如果正常的数据碰巧就包含了BOM呢? 这些情况可不好玩.
为什么会有端的问题呢?我们就不能和睦相处吗?
啊,一个多么具有哲学意义的问题.
任何不同字节顺序的系统都有它的优点.小端机让你先读取小字节数据,从而无需读取其他字节.你可以非常容易地检查一个数据是奇数还是偶数(最后一位是0),如果你有这样的需求.大端机系统以与我们人类思维一致的方式在内存中存储数据(从左到右),这就使得底层的调试变得简单.
为什么我们不都认可一种系统呢? 为什么要尝试这么多的计算机还有这么多的区别呢?
让我用另一个问题来回答这个问题:为什么大家不说同样的语言?为什么有的语言是从左到右写,而有的是从右到左写?
有时候通讯系统是独立开发的,后来就需要互相交流.
结尾: 最后的思考
字节存储顺序这个问题是编码问题中的一个例子。数据需要代表一个抽象的概念,这个概念又需要从数据中创建。这个话题值得在自己的文章中或者系列文章中考虑。你还需要了解更多的关于端相关的问题.
&&&&推荐文章:
【上篇】【下篇】Linux下Valgrind的使用方法_Linux教程_Linux公社-Linux系统门户网站
你好,游客
Linux下Valgrind的使用方法
来源:Linux社区&
作者:Linux
Valgrind是运行在Linux上一套基于仿真技术的程序调试和分析工具,它包含一个内核──一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务──调试,分析,或测试等。Valgrind可以检测内存泄漏和内存违例,还可以分析cache的使用等,灵活轻巧而又强大,能直穿程序错误的心脏,真可谓是程序员的瑞士军刀。
一、Valgrind的主要功能
Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind,Callgrind,Massif。下面分别介绍个工具的作用:
Memcheck 工具主要检查下面的程序错误:
  1.使用未初始化的内存 (Use of uninitialised memory)  2.使用已经释放了的内存 (Reading/writingmemory after it has been free&d)  3.使用超过 malloc分配的内存空间(Reading/writing off the end of malloc&d blocks)  4.对堆栈的非法访问 (Reading/writinginappropriate areas on the stack)  5.申请的空间是否有释放 (Memory leaks &where pointers to malloc&d blocks are lost forever)  6.malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])  7.src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions)Callgrind  Callgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。
Cachegrind& & & & 它模拟 CPU中的一级缓存I1,D1和L2二级缓存,能够精确地指出程序中 cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。
Helgrind  它主要用来检查多线程程序中出现的竞争问题。Helgrind 寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为& Eraser& 的竞争检测算法,并做了进一步改进,减少了报告错误的次数。
Massif  堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率
二. 使用Valgrind Valgrind的使用非常简单,valgrind命令的格式如下:
valgrind [valgrind-options]your-prog [your-prog options]
一些常用的选项如下:
显示帮助信息。
显示valgrind内核的版本,每个工具都有各自的版本。
-q --quiet
安静地运行,只打印错误信息。
-v --verbose
打印更详细的信息。
--tool= [default: memcheck]
最常用的选项。运行valgrind中名为toolname的工具。如果省略工具名,默认运行memcheck。
--db-attach= [default: no]
绑定到调试器上,便于调试错误。
我们通过例子看一下它的具体使用。我们构造一个存在内存泄漏的C程序,如下:
#include &stdio.h&
#include &stdlib.h&
int*Test(void)
& & int* x = malloc(10 * sizeof(int));
& &// problem 1: heap block overrun, problem 2: memory leak --x not free, only first address
int main(void)
& & Test();
& & printf("i =%d/n", count); //problem 3: use uninitialised value.
& & return 0;
$ gcc -Wall -o Test Test.c
$ valgrind --tool=memcheck ./ Test
$valgrind --tool=memcheck --leak-check=yes ./Test
三、安装sudo apt-get install valgrind
Linux下Valgrind的使用概述
Linux下利用Valgrind工具进行内存泄露检测和性能分析
内存泄漏检测工具Valgrind的安装
Valgrind--Linux下的内存调试和代码解剖工具
应用 Valgrind 发现 Linux 程序的内存问题[图文]
本文永久更新链接地址:
相关资讯 & & &
& (04月11日)
& (12/04/:06)
& (11/05/:30)
& (12/14/:07)
& (09/07/:27)
& (08/12/:16)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
World without strangers!
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。Valgrind的体系结构如下图所示:&Valgrind包括如下一些工具,在运行Valgrind时,你必须指明想用的工具,如果省略工具名,默认运行memcheck。1、memcheckmemcheck探测程序中内存管理存在的问题。它检查所有对内存的读/写操作,并截取所有的malloc/new/free/delete调用。因此memcheck工具能够探测到以下问题:1)使用未初始化的内存2)读/写已经被释放的内存3)读/写内存越界4)读/写不恰当的内存栈空间5)内存泄漏6)使用malloc/new/new[]和free/delete/delete[]不匹配。7)src和dst的重叠2、cachegrindcachegrind是一个cache剖析器。它模拟执行CPU中的L1, D1和L2 cache,因此它能很精确的指出代码中的cache未命中。如果你需要,它可以打印出cache未命中的次数,内存引用和发生cache未命中的每一行代码,每一个函数,每一个模块和整个程序的摘要。如果你要求更细致的信息,它可以打印出每一行机器码的未命中次数。在x86和amd64上, cachegrind通过CPUID自动探测机器的cache配置,所以在多数情况下它不再需要更多的配置信息了。3、helgrindhelgrind查找多线程程序中的竞争数据。helgrind查找内存地址,那些被多于一条线程访问的内存地址,但是没有使用一致的锁就会被查出。这表示这些地址在多线程间访问的时候没有进行同步,很可能会引起很难查找的时序问题。它主要用来检查多线程程序中出现的竞争问题。Helgrind 寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为”Eraser” 的竞争检测,并做了进一步改进,减少了报告错误的次数。4、callgrindCallgrind收集程序运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。一般用法:$valgrind --tool=callgrind ./sec_infod会在当前目录下生成callgrind.out.[pid], 如果我们想结束程序, 可以$killall callgrind然后我们可以用$callgrind_annotate --auto=yes callgrind.out.[pid] & log$vi log5、massif堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。6、lackeylackey是一个示例程序,以其为模版可以创建你自己的工具。在程序结束后,它打印出一些基本的关于程序执行统计数据。&linux环境下内存空间分布如上图,一个典型的Linux C程序内存空间由如下几部分组成:代码段(.text):这里存放的是CPU要执行的指令。代码段是可共享的,相同的代码在内存中只会有一个拷贝,同时这个段是只读的,防止程序由于错误而修改自身的指令。初始化数据段(.data):这里存放的是程序中需要明确赋初始值的变量,例如位于所有函数之外的全局变量:int val="100"。需要强调的是,以上两段都是位于程序的可执行文件中,内核在调用exec函数启动该程序时从源程序文件中读入。未初始化数据段(.bss):位于这一段中的数据,内核在执行该程序前,将其初始化为0或者null。例如出现在任何函数之外的全局变量:堆(Heap):这个段用于在程序中进行动态内存申请,例如经常用到的malloc,new系列函数就是从这个段中申请内存。栈(Stack):函数中的局部变量以及在函数调用过程中产生的临时变量都保存在此段中。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的下载与安装1. 到www.valgrind.org下载最新版valgrind-3.2.3.tar.bz22. 解压安装包:tar –jxvf valgrind-3.2.3.tar.bz23. 解压后生成目录valgrind-3.2.34. cd valgrind-3.2.35. 运行./autogen.sh设置环境(需要标准的autoconf工具)(可选)6. ./配置Valgrind,生成MakeFile文件,具体参数信息详见INSTALL文件。一般只需要设置--prefix=/where/you/want/it/installed7. make;编译Valgrind8. make install;安装Valgrind3、Valgrind的使用用法:&valgrind&[options] prog-and-args [options]: 常用选项,适用于所有Valgrind工具-tool=&name& 最常用的选项。运行&valgrind中名为toolname的工具。默认memcheck。h –help 显示帮助信息。-version 显示valgrind内核的版本,每个工具都有各自的版本。q –quiet 安静地运行,只打印错误信息。v –verbose 更详细的信息, 增加错误数统计。-trace-children=no|yes 跟踪子线程? [no]-track-fds=no|yes 跟踪打开的文件描述?[no]-time-stamp=no|yes 增加时间戳到LOG信息? [no]-log-fd=&number& 输出LOG到描述符文件 [2=stderr]-log-file=&file& 将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID-log-file-exactly=&file& 输出LOG信息到 file-log-file-qualifier=&VAR& 取得环境变量的值来做为输出信息的文件名。 [none]-log-socket=ipaddr:port 输出LOG到socket ,ipaddr:portLOG信息输出-xml=yes 将信息以xml格式输出,只有memcheck可用-num-callers=&number& show &number& callers in stack traces [12]-error-limit=no|yes 如果太多错误,则停止显示新错误? [yes]-error-exitcode=&number& 如果发现错误则返回错误代码 [0=disable]-db-attach=no|yes 当出现错误,valgrind会自动启动调试器gdb。[no]-db-command=&command& 启动调试器的命令行选项[gdb -nw %f %p]适用于Memcheck工具的相关选项:-leak-check=no|summary|full 要求对leak给出详细信息? [summary]-leak-resolution=low|med|high how much bt merging in leak check [low]-show-reachable=no|yes show reachable blocks in leak check? [no]3、Valgrind使用示范下面是一段有问题的C程序代码test.c#include &stdlib.h&void f(void){
int* x = malloc(10 * sizeof(int));
x[10] = 0;
//问题1: 数组下标越界}
int main(void){
//问题2: 内存没有释放 }编译程序:gcc -Wall test.c -g -o test使用Valgrind检查程序BUG:valgrind --tool=memcheck --leak-check=full ./test例如如下代码会造成内存泄漏:#include &stdlib.h&int main(){char *x = (char*)malloc(20);char *y = (char*)malloc(20);x=y;free(x);free(y);return 0;}使用valgrind运行结果:==19013== Invalid free() / delete / delete[]==19013== at 0x4A0541E: free (vg_replace_malloc.c:233)==19013== by 0x4004F5: main (sample5.c:8)==19013== Address 0x4C2E078 is 0 bytes inside a block of size 20 free'd==19013== at 0x4A0541E: free (vg_replace_malloc.c:233)==19013== by 0x4004EC: main (sample5.c:7)==19013====19013== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)==19013== malloc/free: in use at exit: 20 bytes in 1 blocks.==19013== malloc/free: 2 allocs, 2 frees, 40 bytes allocated.==19013== For counts of detected errors, rerun with: -v==19013== searching for pointers to 1 not-freed blocks.==19013== checked 66,584 bytes.==19013====19013== LEAK SUMMARY:==19013== definitely lost: 20 bytes in 1 blocks.==19013== possibly lost: 0 bytes in 0 blocks.==19013== still reachable: 0 bytes in 0 blocks.==19013== suppressed: 0 bytes in 0 blocks.==19013== Use --leak-check=full to see details of leaked memory.Valgrind下载地址:http://valgrind.org/downloads/
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_',
blogTitle:'Valgrind工具使用简介',
blogAbstract:'1、引言\tValgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。Valgrind的体系结构如下图所示:',
blogTag:'linux,调试',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:2,
publishTime:0,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'World without strangers!',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}

我要回帖

更多关于 linux valgrind 的文章

 

随机推荐