强力推荐一个内存检测工具valgrind

    技术2022-05-11  20

         今天公司一同事介绍了一个内存检测工具Valgrind,使用过后觉得非常实用,跟rational purify有的一比。

    一、介绍

        Valgrind软件包是open source的,可以在www.valgrind.org下载到,并有很详细的用户文档。包含很多工具,其中一个最有用的就是内存检测工具(Memcheck),可以检测许多通常的内存错误如:

        1、内存越界访问

        2、使用未初始化的变量

        3、错误的释放内存,比如两次释放统一内存块

    4、内存泄露

    二、准备你的程序

        gcc编译程序时加上-g选项,包含调试信息,这样Memcheck才能打印出包含错误行号的错误信息。如果你能忍受编译速度变慢,使用-o0选项也是个不错的选择。使用-o1选项可能会导致错误信息不是很准确。不建议使用-o2以上的选项,否则Memcheck会经常报出未初始化的变量错误信息,但是实际上根本不存在。

    三、在memcheck下运行程序

        正常情况下运行:

           Myprog arg1 arg2

        使用valgrind则如下:

           valgrind --leak-check=yes myprog arg1 arg2  

        Memcheckvalgrind默认使用的工具,--leak-check选项将打开详细的内存泄露检测器。你的程序运行将比正常情况下慢很多,并且将消耗大量的内存。

    四、一个例子

    1、 源代码

    main.c:

    1 #include <stdio.h>

     2 #include <stdlib.h>

     3

     4 void f()

     5 {

     6         int* a = malloc(5*sizeof(int));

      7          a [6]=0;   // 内存越界访问   // 内存泄露

     8 }

     9

    10 int main()

    11 {

    12         f ();

    13         return 0;

    14 }

    2、编译运行

    gcc –g main.c

    valgrind --leak-check=yes ./a.out

    输出结果如下:

    ==19091== Memcheck, a memory error detector.

    ==19091== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.

    ==19091== Using LibVEX rev 1732, a library for dynamic binary translation.

    ==19091== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.

    ==19091== Using valgrind- 3.2.3 , a dynamic binary instrumentation framework.

    ==19091== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.

    ==19091== For more details, rerun with: -v

    ==19091==

    ==19091== Invalid write of size 4

    ==19091==    at 0x80483B3: f (main.c:7)

    ==19091==    by 0x80483D0: main (main.c:12)

    ==19091==  Address 0x4159040 is 4 bytes after a block of size 20 alloc'd

    ==19091==    at 0x4021580: malloc (vg_replace_malloc.c:149)

    ==19091==    by 0x 80483A 9: f (main.c:6)

    ==19091==    by 0x80483D0: main (main.c:12)

    ==19091==

    ==19091== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 7 from 1)

    ==19091== malloc/free: in use at exit: 20 bytes in 1 blocks.

    ==19091== malloc/free: 1 allocs, 0 frees, 20 bytes allocated.

    ==19091== For counts of detected errors, rerun with: -v

    ==19091== searching for pointers to 1 not-freed blocks.

    ==19091== checked 52,748 bytes.

    ==19091==

    ==19091==

    ==19091== 20 bytes in 1 blocks are definitely lost in loss record 1 of 1

    ==19091==    at 0x4021580: malloc (vg_replace_malloc.c:149)

    ==19091==    by 0x 80483A 9: f (main.c:6)

    ==19091==    by 0x80483D0: main (main.c:12)

    ==19091==

    ==19091== LEAK SUMMARY:

    ==19091==    definitely lost: 20 bytes in 1 blocks.

    ==19091==      possibly lost: 0 bytes in 0 blocks.

    ==19091==    still reachable: 0 bytes in 0 blocks.

    ==19091==         suppressed: 0 bytes in 0 blocks.

    第一个问题,访问越界信息如下:

    ==19091== Invalid write of size 4

    ==19091==    at 0x80483B3: f (main.c:7)

    ==19091==    by 0x80483D0: main (main.c:12)

    ==19091==  Address 0x4159040 is 4 bytes after a block of size 20 alloc'd

    ==19091==    at 0x4021580: malloc (vg_replace_malloc.c:149)

    ==19091==    by 0x 80483A 9: f (main.c:6)

    ==19091==    by 0x80483D0: main (main.c:12)

    Things to notice:

    ·         There is a lot of information in each error message; read it carefully.

    ·         The 19091is the process ID; it's usually unimportant.

    ·         The first line ("Invalid write...") tells you what kind of error it is. Here, the program wrote to some memory it should not have due to a heap block overrun.

    ·         Below the first line is a stack trace telling you where the problem occurred. Stack traces can get quite large, and be confusing, especially if you are using the C++ STL. Reading them from the bottom up can help. If the stack trace is not big enough, use the --num-callers option to make it bigger.

    ·         The code addresses (eg. 0x 80483A 9) are usually unimportant, but occasionally crucial for tracking down weirder bugs.

    ·         Some error messages have a second component which describes the memory address involved. This one shows that the written memory is just past the end of a block allocated with malloc() on line 5 of main.c.

    It's worth fixing errors in the order they are reported, as later errors can be caused by earlier errors.

    第二个问题,内存泄露信息如下:

    ==19091== 20 bytes in 1 blocks are definitely lost in loss record 1 of 1

    ==19091==    at 0x4021580: malloc (vg_replace_malloc.c:149)

    ==19091==    by 0x 80483A 9: f (main.c:6)

    ==19091==    by 0x80483D0: main (main.c:12)

    The stack trace tells you where the leaked memory was allocated. Memcheck cannot tell you why the memory leaked, unfortunately. (Ignore the "vg_replace_malloc.c", that's an implementation detail.)

    There are several kinds of leaks; the two most important categories are:

    ·         "definitely lost": your program is leaking memory -- fix it!

    ·         "probably lost": your program is leaking memory, unless you're doing funny things with pointers (such as moving them to point to the middle of a heap block).

    If you don't understand an error message, please consult Explanation of error messages from Memcheck in the Valgrind User Manual which has examples of all the error messages Memcheck produces.

     


    最新回复(0)