开始写第一篇的时候就是想记录一下自己当时怎么用的,后来想想还是应该深入的了解一下,方便以后使用。
所以我在官网下了使用手册来看看,并且自己写程序一点一点的分析,故意出错,看会给什么相应的信息。
官网手册下载地址:http://valgrind.org/docs/download_docs.html
对了补充一下:每个信息前面都有一个数字,并且每次的都是一样的,这个是进程ID号
在补充一点:就是在使用valgrind的时候信息是输出到标准错误上的,也就是stderr,文件描述符一般就是2了,所以我们在屏幕上运行的时候,一般打印到屏幕上是很乱的,所以输出到文件中比较容易查阅,这里重定向要使用 2> 文件名,比如:
valgrind --leak-check=full ./a.out 2> record.txt
当然了,如果你蛋疼可以这么写:
valgrind --leak-check=full -v --log-fd=1 ./a.out > record.txt
--log-fd=1就是valgrind自己的内部选项,把日志重定向到相应描述符上,先定向到1就是标准输出,然后后面直接使用 >也是可以的,但是。。。。。。。。。。
当然了,还有一种办法就是直接使用文件名的:
valgrind --leak-check=full --log-file=record.txt ./a.out
这样也是输出到那个文件中了,貌似这个多进程的时候更有用,但我还不知道有什么用,看到了再补充。
终于看到是为什么了,这个多进程指定文件后,可以把不同进程的输出到相应的文件中,这样用:
valgrind --leak-check=full --log-file=record.%p ./a.out
这样就是按进程ID来输出到相应的文件中,%p就是进程ID匹配用,但是好像只能是两个进程,多个进程好像只输出
前两个了,还需要进一步使用看看,好了初步学习的记录就到这,要不然太长了。
写最简单的程序
test.cpp
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
return 0; }
编译成a.out后,对了,在编译的时候,加上-g,这样在valgrind的信息中会有代码行号等信息,使用valgrind来查看:
valgrind --leak-check=full ./a.out 2> record.txt
==6977== Memcheck, a memory error detector ==6977== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==6977== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==6977== Command: ./a.out ==6977== ==6977== ==6977== HEAP SUMMARY: ==6977== in use at exit: 0 bytes in 0 blocks ==6977== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==6977== ==6977== All heap blocks were freed -- no leaks are possible ==6977== ==6977== For counts of detected and suppressed errors, rerun with: -v ==6977== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
上面就是所有输出内容。差不多就这么多。
2. 然后用一个带有没有free或者delete泄漏的。
#include <iostream>
using namespace std;
struct xx { int a; int b; int c; };
int main(int argc, char *argv[]) { xx *x = new xx;
return 0; }
使用valgrind查看结果如下:
==7048== Memcheck, a memory error detector ==7048== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==7048== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==7048== Command: ./a.out ==7048== ==7048== ==7048== HEAP SUMMARY: ==7048== in use at exit: 12 bytes in 1 blocks ==7048== total heap usage: 1 allocs, 0 frees, 12 bytes allocated ==7048== ==7048== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==7048== at 0x4A075BC: operator new(unsigned long) (vg_replace_malloc.c:298) ==7048== by 0x4006DC: main (test.cpp:13) ==7048== ==7048== LEAK SUMMARY: ==7048== definitely lost: 12 bytes in 1 blocks ==7048== indirectly lost: 0 bytes in 0 blocks ==7048== possibly lost: 0 bytes in 0 blocks ==7048== still reachable: 0 bytes in 0 blocks ==7048== suppressed: 0 bytes in 0 blocks ==7048== ==7048== For counts of detected and suppressed errors, rerun with: -v ==7048== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
这就有问题了,并且告诉的非常明确:
==7048== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7048== at 0x4A075BC: operator new(unsigned long) (vg_replace_malloc.c:298)
==7048== by 0x4006DC: main (test.cpp:13)
第一行是说:definitely lost (肯定丢了),这是12bytes
第二行是说:调用了new的时候
第三行是说:在调用main()函数的时候
12字节刚好是我们上面定义那个结构体的大小三个int型,12个字节
这样就找到了问题,是new了但是没有delete,然后加上delete后,再运行看结果
==7164== Memcheck, a memory error detector ==7164== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==7164== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==7164== Command: ./a.out ==7164== ==7164== ==7164== HEAP SUMMARY: ==7164== in use at exit: 0 bytes in 0 blocks ==7164== total heap usage: 1 allocs, 1 frees, 12 bytes allocated ==7164== ==7164== All heap blocks were freed -- no leaks are possible ==7164== ==7164== For counts of detected and suppressed errors, rerun with: -v ==7164== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
又成这样了,说明解决了。这次练习到这里,之后深入学习
3. 下面用了malloc,但是没有free
#include <iostream> #include <cstdlib>
using namespace std;
struct xx { int a; int b; int c; };
int main(int argc, char *argv[]) { xx *x = new xx;
xx *p = (xx *)malloc(sizeof(xx));
return 0; }
输出结果是这样的:
==7433== Memcheck, a memory error detector ==7433== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==7433== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==7433== Command: ./a.out ==7433== ==7433== ==7433== HEAP SUMMARY: ==7433== in use at exit: 24 bytes in 2 blocks ==7433== total heap usage: 2 allocs, 0 frees, 24 bytes allocated ==7433== ==7433== 12 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==7433== at 0x4A075BC: operator new(unsigned long) (vg_replace_malloc.c:298) ==7433== by 0x40071C: main (test.cpp:14) ==7433== ==7433== 12 bytes in 1 blocks are definitely lost in loss record 2 of 2 ==7433== at 0x4A069EE: malloc (vg_replace_malloc.c:270) ==7433== by 0x40072A: main (test.cpp:16) ==7433== ==7433== LEAK SUMMARY: ==7433== definitely lost: 24 bytes in 2 blocks ==7433== indirectly lost: 0 bytes in 0 blocks ==7433== possibly lost: 0 bytes in 0 blocks ==7433== still reachable: 0 bytes in 0 blocks ==7433== suppressed: 0 bytes in 0 blocks ==7433== ==7433== For counts of detected and suppressed errors, rerun with: -v ==7433== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 6 from 6)
这里就有两个definitely了,这是那个new和malloc都没有释放的原因,最后一句也告诉我们,有两处错误
LEAK SUMMARY:告诉我们,有两个blocks泄漏,共24字节
ERROR SUMMARY:告诉我们,有两处内存肯定泄漏的错误
4. 然后我们进去内存越界访问,先用malloc分配的数组尝试,分配了10个int大小,但是却访问之后的一个int:
#include <iostream> #include <cstdlib>
using namespace std;
struct xx { int a; int b; int c; };
int main(int argc, char *argv[]) { xx *x = new xx;
xx *p = (xx *)malloc(sizeof(xx));
int *parray = (int *)malloc(10 * sizeof(int)); parray[10] = 1;
delete x; free(p); free(parray);
return 0; }
这样会有相应的提示信息告诉我们错误:
==7649== Memcheck, a memory error detector ==7649== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==7649== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==7649== Command: ./a.out ==7649== ==7649== Invalid write of size 4 ==7649== at 0x4007D5: main (test.cpp:19) ==7649== Address 0x4c29108 is 0 bytes after a block of size 40 alloc'd ==7649== at 0x4A069EE: malloc (vg_replace_malloc.c:270) ==7649== by 0x4007C8: main (test.cpp:18) ==7649== ==7649== ==7649== HEAP SUMMARY: ==7649== in use at exit: 0 bytes in 0 blocks ==7649== total heap usage: 3 allocs, 3 frees, 64 bytes allocated ==7649== ==7649== All heap blocks were freed -- no leaks are possible ==7649== ==7649== For counts of detected and suppressed errors, rerun with: -v ==7649== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
错误信息是这样的:Invalid write of size 4
并且告诉我们在main.c的第19行,就是这里我们越界了。
5. 下面我们不用malloc分配,直接在栈上分配,看看越界会不会有提示:
#include <iostream> #include <cstdlib>
using namespace std;
struct xx { int a; int b; int c; };
int main(int argc, char *argv[]) { xx *x = new xx;
xx *p = (xx *)malloc(sizeof(xx));
int *parray = (int *)malloc(10 * sizeof(int)); parray[9] = 1;
delete x; free(p); free(parray);
int array[10]; array[10] = 1;
return 0; }
下面是提示信息:
==7765== Memcheck, a memory error detector ==7765== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==7765== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==7765== Command: ./a.out ==7765== ==7765== ==7765== HEAP SUMMARY: ==7765== in use at exit: 0 bytes in 0 blocks ==7765== total heap usage: 3 allocs, 3 frees, 64 bytes allocated ==7765== ==7765== All heap blocks were freed -- no leaks are possible ==7765== ==7765== For counts of detected and suppressed errors, rerun with: -v ==7765== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)
看,这里是没有错误的,所以这种是不提示的,只是分析heap也就是堆上的内存问题的。