Valgrind 文档
时间:2006-09-15 来源:blueshycool
文档标识 |
Valgrind-20060914-00 |
作 者 |
Blueshycool(杨友发) |
创建时间 |
2006-9-14 |
相关文档 |
无 |
文档说明 |
Valgrind使用手册(有待日后完善) |
Valgrind使用手册 |
一, Valgrind概述 Valgrind是x86架构Linux上的多重用途代码剖析和内存调试工具。但它的主要功能还是对内存的调试,而且它的默认工具也是启动memcheck。你可以在它的环境中运行你的程序来监视内存的使用情况,比如C语言中的malloc和free或者C++中的new和delete。 Valgrind的主要功能: 1,使用未初始化的内存(Use of uninitialised memory) 2,使用已经释放了的内存(Reading/writing memory after it has been free'd) 3,使用超过malloc分配的内存空间(Reading/writing off the end of malloc'd blocks) 4,对堆栈的非法访问(Reading/writing inappropriate 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) 二, Valgrind安装 1, 解压valgrind-3.2.0.tar.bz2 $bunzip2 valgrind-3.2.0.tar.bz2 $tar vfx valgrind-3.2.0.tar 解压后生成一个 valgrind-3.2.0目录 $cd valgrind-3.2.0 2, 编译安装valgrind $./configure $make && make install 到这里valgrind就编译安装完成。 三, Valgrind使用参数 内存泄漏是最难发现的常见错误之一,因为除非用完内存或调用malloc失败,否则都不会导致任何问题。实际上,使用像C或C++这类没有垃圾回收机制的语言时,你一大半的时间都花费在处理如何正确释放内存上。如果程序运行时间足够长,一个小小的失误也会对程序造成重大的影响。 Valgrind支持很多工具:memcheck,addrcheck,cachegrind,massif,helgrind和callgrind等。在运行Valgrind时,你必须指明想用的工具。如$valgrind –tool=memcheck test,将对test进行内存使用情况进行分析,包括malloc/free/new/new[]/delete。 如果没有其它参数,Valgrind在程序结束后给出关于free/delete和malloc/new总 共调用次数的简报。 1, Valgrind使用参数 --log-fd=N 默认情况下,输出信息是到标准错误stderr,也可以通过—log-fd=8,输出到描述符为8的文件 --log-file=filename将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID。可以通过--log-file-exactly=filename指定就输出到filename文件。 --log-file-qualifier=<VAR>,取得环境变量的值来做为输出信息的文件名。如—log-file-qualifier=$FILENAME。 --log-socket=IP:PORT 也可以把输出信息发送到网络中指定的IP:PORT去 --error-limit=no 对错误报告的个数据进行限制,默认情况不做限制 --tool=<toolname> [default: memcheck] --tool=memcheck:要求用memcheck这个工具对程序进行分析 --leak-ckeck=yes 要求对leak给出详细信息 --trace-children=<yes|no> [default: no] 跟踪到子进程里去,默认请况不跟踪 --xml=<yes|no> [default: no] 将信息以xml格式输出,只有memcheck可用 --gen-suppressions=<yes|no|all> [default: no] 如果为yes,valgrind会在每发现一个错误便停下让用户做选择是继续还是 退出更多选项请参看: http://www.valgrind.org/docs/manual/manual-core.html可以把一些默认选项编辑在 ~/.valgrindrc文件里。 2, 用Valgrind查找内存泄漏 我们必须带上这个参数: --leak-check=<no|summary|yes|full> [default: summary] Leak是指,存在一块没有被引用的内存空间,或没有被释放的内存空间,如summary,只反馈一些总结信息,告诉你有多少个malloc,多少个free 等;如果是full将输出所有的leaks,也就是定位到某一个malloc/free。 --show-reachable=<yes|no> [default: no] 如果为no,只输出没有引用的内存leaks,或指向malloc返回的内存块中部某处的leaks --leak-resolution=<low|med|high> [default: low] When doing leak checking, determines how willing memcheck is to consider different backtraces to be the same. When set to low, only the first two entries need match. When med, four entries have to match. When high, all entries need to match.For hardcore leak debugging, you probably want to use --leak-resolution=high together with --num-callers=40 or some such large number. Note however that this can give an overwhelming amount of information, which is why the defaults are 4 callers and low-resolution matching.Note that the --leak-resolution= setting does not affect memcheck's ability to finds. It only changes how the results are presented. --freelist-vol=<number> [default: 5000000] 当free/delete之后并不将释放的内存设置成可以代realloc用,而是放入一个`空闲队列中,如果队列中的内存块大于<number>时才允许用于realloc --workaround-gcc296-bugs=<yes|no> [default: no] When enabled, assume that reads and writes some small distance below the stack pointer are due to bugs in gcc 2.96, and does not report them. The "small distance" is 256 bytes by default. Note that gcc 2.96 is the default compiler on some older Linux distributions (RedHat 7.X) and so you may need to use this flag. Do not use it if you do not have to, as it can cause real errors to be overlooked. A better alternative is to use a more recent gcc/g++ in which this bug is fixed. --partial-loads-ok=<yes|no> [default: no] Controls how memcheck handles word-sized, word-aligned loads from addresses for which some bytes are addressible and others are not. When yes, such loads do not elicit an address error. Instead, the loaded V bytes corresponding to the illegal addresses indicate Undefined, and those corresponding to legal addresses are loaded from shadow memory, as usual.When no, loads from partially invalid addresses are treated the same as loads from completely invalid addresses: an illegal-address error is issued, and the resulting V bytes indicate valid data. --undef-value-errors=<yes|no> [default: yes] 如果为yes,memcheck将对无定义值错进行检查
四,Valgrind memcheck的功能 假设我们有一个test.cc源程序,如下: 5 void foo(int y) { 6 int *x = new int; 7 printf("y=%d\n", y); 8 } 9 int main() { 10 int y; 11 int *z = (int*) malloc(8); 12 char *q = new char[4]; 13 char *p = (char*) malloc(4); 14 write( 1 /* stdout */, p, 4); 15 q[4] = 'x'; // MAGIC overrun 16 foo(y); 17 free(z); 18 *z = 100; 19 delete p; 20 memcpy(q, q+1, 3); 21 delete q; 22 delete q; // delete value twice 23 } $g++ -g –o test test.cc 编译完后生成一个可执行文件test,这时我们可以用 $ valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./test 我们可以看看输出的结果,最左边是运行进程号: 1, 使用未初始化的内存或变量(Use of uninitialised memory) ==18557== Use of uninitialised value of size 4 ==18557== at 0x24162C: vfprintf (in /lib/tls/libc-2.3.3.so) ==18557== by 0x247421: printf (in /lib/tls/libc-2.3.3.so) ==18557== by 0x80485D5: foo(int) (test.cc:7) ==18557== by 0x8048641: main (test.cc:16) 代码中我们没有对y进行初始化便传给了foo();所以给出了使用用了未初始化的值! 2, 使用已经释放了的内存(Reading/writing memory after it has been free'd) ==18557== Invalid free() / delete / delete[] ==18557== at 0x400535D: operator delete(void*) (vg_replace_malloc.c:244) ==18557== by 0x8048697: main (test.cc:22) ==18557== Address 0x401F060 is 0 bytes inside a block of size 4 free'd ==18557== at 0x400535D: operator delete(void*) (vg_replace_malloc.c:244) ==18557== by 0x8048689: main (test.cc:21) 代码中我们对q进行了两次delete! 3, 使用超过malloc分配的内存空间或下标越界(Reading/writing off the end of malloc'd blocks) ==18557== Invalid write of size 1 ==18557== at 0x8048634: main (test.cc:15) ==18557== Address 0x401F064 is 0 bytes after a block of size 4 alloc'd ==18557== at 0x4004D1D: operator new[](unsigned) (vg_replace_malloc.c:195) ==18557== by 0x8048605: main (test.cc:12) 也就是指q[4]=’x’那句,相当于相标越界了! 4, 申请的空间是否有释放(Memory leaks -- where pointers to malloc'd blocks are lost forever ==18557== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==18557== at 0x40048B3: operator new(unsigned) (vg_replace_malloc.c:163) ==18557== by 0x80485BF: foo(int) (test.cc:6) ==18557== by 0x8048641: main (test.cc:16). 在foo()里申请了4个字节的内存空间但并没有被delete! 5, malloc/free/new/delete申请和释放内存的匹配(Mismatched use of malloc/new/new[]vs free/delete/delete [] ==18557== Mismatched free() / delete / delete [] ==18557== at 0x400535D: operator delete(void*) (vg_replace_malloc.c:244) ==18557== by 0x8048689: main (test.cc:21) ==18557== Address 0x401F060 is 0 bytes inside a block of size 4 alloc'd ==18557== at 0x4004D1D: operator new[](unsigned) (vg_replace_malloc.c:195) ==18557== by 0x8048605: main (test.cc:12) 代码的21行p并不是通过new而得来的,但是却被delete! 6, src和dst的重叠(Overlapping src and dst pointers in memcpy() and related functions) ==18557== Source and destination overlap in memcpy(0x401F060, 0x401F061, 3) ==18557== at 0x40065D1: memcpy (mc_replace_strmem.c:116) ==18557== by 0x804867B: main (test.cc:20) Memcpy()的src和dest发生了重叠!
通过对给出的信息进行分析,我们可以知道,是哪一行代码malloc/free,哪里的Malloc/new没有free/delete。根据这些信息再对代码做些相应的调整!在运行Valgrind时加上--show-reachable=yes参数,可以找到每一个未来匹配的free或new,输出结果和上面差不多,不过显示了更多未释放的内存。
五, Valgreind要注意的问题 Valgrind是x86架构上的工具,只能在Linux上运行(FreeBSD和NetBSD上的相关版本正在开发中)。它允许程序员在它的环境里测试程序以检测未配对malloc调用错误和其它使用非法内存(未初始化内存)的错误以及非法内存操作(比如同一块内存 释放两次或调用不正确的析构函数)。Valgrind不检查静态分配数组的使用情况。更详细的帮助文件在 http://www.valgrind.org/docs/manual/manual.html |