Valgrind是一款开源内存使用问题检测工具,3.7.0版本的下载地址为http://valgrind.org/downloads/valgrind-3.7.0.tar.bz2。
今天,对它做一下初步的测试,测试平台Ubuntu 10.04 64bit。
下载完成后,解压源码,执行./configure;make;make install后,默认安装到/usr/local/bin下,执行:
valgrind ls -l
提示:
==14336== Memcheck, a memory error detector
==14336== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==14336== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==14336== Command: ls -l
==14336==
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: strlen
valgrind: in an object with soname matching: ld-linux-x86-64.so.2
valgrind: was not found whilst processing
valgrind: symbols from the object with soname: ld-linux-x86-64.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.
大概是说我的glibc是个strip后的版本,需要下载debug版,debug版的名字是libc6-dbg。
执行:
sudo apt-get install libc6-dbg
==14378== Memcheck, a memory error detector
==14378== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==14378== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==14378== Command: ls -l
==14378==
total 108
drwxr-xr-x 2 root root 4096 2012-07-13 03:26 bin
drwxr-xr-x 3 root root 4096 2012-07-13 07:36 boot
drwxr-xr-x 2 root root 4096 2012-07-13 07:06 cdrom
drwxr-xr-x 17 root root 3620 2012-07-24 03:00 dev
drwxr-xr-x 128 root root 12288 2012-07-24 03:06 etc
drwxr-xr-x 3 root root 4096 2012-07-13 08:16 home
lrwxrwxrwx 1 root root 33 2012-07-13 07:07 initrd.img -> boot/initrd.img-2.6.32-38-generic
drwxr-xr-x 16 root root 12288 2012-07-13 03:23 lib
drwxr-xr-x 2 root root 4096 2012-07-13 03:24 lib32
lrwxrwxrwx 1 root root 4 2012-07-13 07:03 lib64 -> /lib
drwx------ 2 root root 16384 2012-07-13 07:03 lost+found
drwxr-xr-x 4 root root 4096 2012-07-13 02:13 media
drwxr-xr-x 2 root root 4096 2012-02-03 04:21 mnt
drwxr-xr-x 2 root root 4096 2012-07-13 07:03 opt
dr-xr-xr-x 182 root root 0 2012-07-24 02:58 proc
drwx------ 8 root root 4096 2012-07-24 21:25 root
drwxr-xr-x 2 root root 4096 2012-07-16 01:21 sbin
drwxr-xr-x 2 root root 4096 2009-12-05 17:25 selinux
drwxr-xr-x 2 root root 4096 2012-07-13 07:03 srv
drwxr-xr-x 13 root root 0 2012-07-24 02:58 sys
drwxrwxrwx 2 root root 4096 2012-07-16 01:39 tftpboot
drwxrwxrwt 14 root root 4096 2012-07-24 21:31 tmp
drwxr-xr-x 11 root root 4096 2012-07-13 03:23 usr
drwxr-xr-x 15 root root 4096 2012-07-13 07:31 var
lrwxrwxrwx 1 root root 30 2012-07-13 07:07 vmlinuz -> boot/vmlinuz-2.6.32-38-generic
drwxrwxrwx 6 root root 4096 2012-07-24 03:02 work
==14378==
==14378== HEAP SUMMARY:
==14378== in use at exit: 20,081 bytes in 58 blocks
==14378== total heap usage: 1,798 allocs, 1,740 frees, 164,568 bytes allocated
==14378==
==14378== LEAK SUMMARY:
==14378== definitely lost: 240 bytes in 3 blocks
==14378== indirectly lost: 480 bytes in 20 blocks
==14378== possibly lost: 0 bytes in 0 blocks
==14378== still reachable: 19,361 bytes in 35 blocks
==14378== suppressed: 0 bytes in 0 blocks
==14378== Rerun with --leak-check=full to see details of leaked memory
==14378==
==14378== For counts of detected and suppressed errors, rerun with: -v
==14378== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
看来ls这个命令是没有任何内存问题的。。。
好了,我们自己写一段吧:
#include
/*
* === FUNCTION ======================================================================
* Name: bug
* Description:
* =====================================================================================
*/
void bug ( )
{
int a[100], * b, * c;
b = new int[100];
// memset(a, 0, 2000);
a[100] = 0;
b[100] = 0;
*c = 0;
} /* ----- end of function bug ----- */
/*
* === FUNCTION ======================================================================
* Name: main
* Description:
* =====================================================================================
*/
int main ( int argc, char *argv[] )
{
bug();
return 0;
} /* ---------- end of function main ---------- */
==14525== Memcheck, a memory error detector
==14525== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==14525== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==14525== Command: ./membug
==14525==
==14525== Invalid write of size 4
==14525== at 0x40064E: bug() (membug.cpp:14)
==14525== by 0x400673: main (membug.cpp:25)
==14525== Address 0x59601d0 is 0 bytes after a block of size 400 alloc'd
==14525== at 0x4C28112: operator new[](unsigned long) (vg_replace_malloc.c:348)
==14525== by 0x400638: bug() (membug.cpp:11)
==14525== by 0x400673: main (membug.cpp:25)
==14525==
==14525== Use of uninitialised value of size 8
==14525== at 0x400658: bug() (membug.cpp:15)
==14525== by 0x400673: main (membug.cpp:25)
==14525==
==14525== Invalid write of size 4
==14525== at 0x400658: bug() (membug.cpp:15)
==14525== by 0x400673: main (membug.cpp:25)
==14525== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14525==
==14525==
==14525== Process terminating with default action of signal 11 (SIGSEGV)
==14525== Access not within mapped region at address 0x0
==14525== at 0x400658: bug() (membug.cpp:15)
==14525== by 0x400673: main (membug.cpp:25)
==14525== If you believe this happened as a result of a stack
==14525== overflow in your program's main thread (unlikely but
==14525== possible), you can try to increase the size of the
==14525== main thread stack using the --main-stacksize= flag.
==14525== The main thread stack size used in this run was 8388608.
==14525==
==14525== HEAP SUMMARY:
==14525== in use at exit: 400 bytes in 1 blocks
==14525== total heap usage: 1 allocs, 0 frees, 400 bytes allocated
==14525==
==14525== 400 bytes in 1 blocks are still reachable in loss record 1 of 1
==14525== at 0x4C28112: operator new[](unsigned long) (vg_replace_malloc.c:348)
==14525== by 0x400638: bug() (membug.cpp:11)
==14525== by 0x400673: main (membug.cpp:25)
==14525==
==14525== LEAK SUMMARY:
==14525== definitely lost: 0 bytes in 0 blocks
==14525== indirectly lost: 0 bytes in 0 blocks
==14525== possibly lost: 0 bytes in 0 blocks
==14525== still reachable: 400 bytes in 1 blocks
==14525== suppressed: 0 bytes in 0 blocks
==14525==
==14525== For counts of detected and suppressed errors, rerun with: -v
==14525== Use --track-origins=yes to see where uninitialised values come from
==14525== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 2 from 2)
Segmentation fault
可以看出valgrind定位出了第11行的内存泄漏,第14行的越界访问,第15行的野指针访问,但对13行的数组越界无动于衷。实际运行可以发现,对数组a的也并未引起程序异常,这是为什么呢?原因是因为数组a是在栈中分配的空间,对a[100]的写入并未引起程序栈出现异常,可以说仅在这个时候没引起异常。为了加大栈溢出访问的影响,可以改成memset(a, 0, 2000),运行后发现valgrind会发现问题,可是由于栈数据丢失,已经不能分析出有问题的地方了。
续:valgrind的mips补丁,有空可以试一下:https://bugs.kde.org/show_bug.cgi?id=270777