} } }

    调不尽的内存泄漏,用不完的Valgrind

    添加时间:2013-7-2 点击量:

    调不尽的内存泄漏,用不完的Valgrind


    Valgrind 安装


    1. 到www.valgrind.org新版valgrind-X.X.X.tar.bz2


    2. 解压安装包:tar –jxvf valgrind-3.2.3.tar.bz2


    3. 解压后生成目次valgrind-3.2.3


    4. cd valgrind-3.2.3


    5. 运行./autogen.sh设置景象(须要标准的autoconf对象)(可选)


    6. ./configure;设备Valgrind,生成MakeFile文件,具体参数信息详见INSTALL文件。一般只须要设置--prefix=/where/you/want/it/installed


    7. Make;编译Valgrind


    8. make install;安装Valgrind


    Valgrind包含的对象


    Valgrind支撑很多对象:memcheck,addrcheck,cachegrind,Massif,helgrind和Callgrind等。在运行Valgrind时,你必须指明想用的对象,若是省略对象名,默认运行memcheck。


    1、memcheck


    memcheck探测法度中内存经管存在的题目。它搜检所有对内存的读/写操纵,并截取所有的malloc/new/free/调用。是以memcheck对象可以或许探测到以下题目:


    1)应用未初始化的内存


    2)读/写已经被开释的内存


    3)读/写内存越界


    4)读/写不恰当的内存栈空间


    5)内存泄漏


    6)应用malloc/new/new[]和free//[]不匹配。


    7)src和dst的重叠


    2、cachegrind


    cachegrind是一个cache解析器。它模仿履行CPU中的L1, D1和L2 cache,是以它能很正确的指出代码中的cache未射中。若是你须要,它可以打印出cache未射中的次数,内存引用和产生cache未射中的每一行代码,每一个函数,每一个模块和全部法度的择要。若是你请求更详尽的信息,它可以打印出每一行机械码的未射中次数。在x8amd64上, cachegrind经由过程CPUID主动探测机械的cache设备,所以在多半景象下它不再须要更多的设备信息了。


    3、helgrind


    helgrind查找多线程法度中的竞争数据。helgrind查找内存地址,那些被多于一条线程接见的内存地址,然则没有应用一致的锁就会被查出。这默示这些地址在多线程间接见的时辰没有进行同步,很可能会引起很难查找的时序题目。


    它首要用来搜检多线程法度中呈现的竞争题目。Helgrind 寻找内存中被多个线程接见,而又没有一贯加锁的区域,这些区域往往是线程之间落空同步的处所,并且会导致难以发掘的错误。Helgrind实现了名为”Eraser” 的竞争检测算法,并做了进一步改进,削减了呈报错误的次数。


    4、Callgrind


    Callgrind收集法度运行时的一些数据,函数调用关系等信息,还可以有选择地进行cache 模仿。在运行停止时,它会把解析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的情势。


    一般用法:


    ¥valgrind --tool=callgrind ./sec_infod


    会在当前目次下生成callgrind.out.[pid], 若是我们想停止法度, 可以


    ¥killall callgrind


    然后我们可以用


    ¥callgrind_annotate --auto=yes callgrind.out.[pid] > log


    ¥vi log


    5、Massif


    客栈解析器,它能测量法度在客栈中应用了几许内存,告诉我们堆块,堆经管块和栈的大小。Massif能帮助我们削减内存的应用,在带有虚拟内存的现代体系中,它还可以或许加快我们法度的运行,削减法度逗留在互换区中的几率。


    6、lackey


    lackey是一个示例法度,以其为模版可以创建你本身的对象。在法度停止后,它打印出一些根蒂根基的关于法度履行统计数据。


    Valgrind的参数


    用法: valgrind [options] prog-and-args [options]: 常用选项,实用于所有Valgrind对象


    --tool=<name>


    最常用的选项。运行 valgrind中名为toolname的对象。默认memcheck。


    -h --help


    显示所有选项的帮助,包含内核和选定的对象两者。


    --version


    显示valgrind内核的版本,每个对象都有各自的版本。


    -q --quiet


    安适地运行,只打印错误信息。


    --verbose


    更具体的信息。


    --trace-children=<yes|no>


    跟踪子线程? [default: no]


    --track-fds=<yes|no>


    跟踪打开的文件描述?[default: no]


    --time-stamp=<yes|no>


    增长时候戳到LOG信息? [default: no]


    --log-fd=<number>


    输出LOG到描述符文件 [2=stderr]


    --log-file=<file>


    将输出的信息写入到filename.PID的文件里,PID是运行法度的进行ID


    --log-file-exactly=<file>


    输出LOG信息到 file


    LOG信息输出


    --xml=yes


    将信息以xml格局输出,只有memcheck可用


    --num-callers=<number>


    show <number> callers in stack traces [12]


    --error-exitcode=<number>


    若是发明错误则返回错误代码 [0=disable]


    --db-attach=<yes|no>


    当呈现错误,valgrind会主动启动调试器gdb。[default: no]


    --db-command=<command>


    启动调试器的号令行选项[gdb -nw %f %p]


    实用于Memcheck对象的相干选项:


    --leak-check=<no|summary|full>


    请求对leak给出具体信息? Leak是指,存在一块没有被引用的内存空间,或没有被开释的内存空间,如summary,只反馈一些总结信息,告诉你有几许个malloc,几许个free 等;若是是full将输出所有的leaks,也就是定位到某一个malloc/free。 [default: summary]


    --show-reachable=<yes|no>


    若是为no,只输出没有引用的内存leaks,或指向malloc返回的内存块中部某处的leaks [default: no]


    更具体的参数指令见附录A。


    Valgrind的应用


    起首,在编译法度的时辰打开调试模式(gcc编译器的-g选项)。若是没有调试信息,即使好的valgrind对象也将中可以或许猜测特定的代码是属于哪一个函数。打开调试选项进行编译后再用valgrind搜检,valgrind将会给你的个具体的呈报,比如哪一行代码呈现了内存泄漏。


    当搜检的是C++法度的时辰,还应当推敲另一个选项 -fno-inline。它使得函数调用链很清楚,如许可以削减你在浏览大型C++法度时的杂沓。比如在应用这个选项的时辰,用memcheck搜检openoffice就很轻易。当然,你可能不会做这项工作,然则应用这一选项使得valgrind生成更正确的错误呈报和削减杂沓。


    一些编译优化选项(比如-O2或者更高的优化选项),可能会使得memcheck提交错误的未初始化呈报,是以,为了使得valgrind的呈报更正确,在编译的时辰好不要应用优化选项。


    若是法度是经由过程脚本启动的,可以批改脚本里启动法度的代码,或者应用--trace-children=yes选项来运行脚本。


    下面是用memcheck搜检sample.c的例子


    这里用到的示例法度文件名为:sample.c(如下所示),选用的编译器为gcc。


    生成可履行法度


    gcc –g sample.c –o sample


    图1


    运行Valgrind


    valgrind --tool=memcheck ./sample


    以下是运行上述号令后的输出


    图2


    左边显示类似行号的数字(10297)默示的是 Process ID。


    最上方的红色方框默示的是 valgrind 的版本信息。


    中心的红色方框默示 valgrind 经由过程运行被测试法度,发明的内存题目。经由过程浏览这些信息,可以发明:


    l 这是一个对内存的不法写操纵,不法写操纵的内存是4 bytes。


    l 产生错误时的函数客栈,以及具体的源代码行号。


    l 不法写操纵的具体地址空间。


    最下面的红色方框是对发明的内存题目和内存泄目的总结。内存泄漏的大小(40 bytes)也可以或许被检测出来。


    Valgrind的示例


    1.应用未初始化的内存


    代码如下


     


    #include <stdio.h>                                                             

    int main()

    {

        int x;

        if(x == 0)

        {

            printf(X is zero);

        }

        return 0;

    }




    Valgrind提示如下

    ==14222== Conditional jump or move depends on
    uninitialised value(s)

    ==14222== at 0 x400484: main (sample2.c:6)

    X is zero==14222==

    ==14222== ERROR SUMMARY: 1 errors 1 contexts (suppressed: 5 1)

    ==14222== malloc/free: in use at exit: 0 bytes in 0 blocks.

    ==14222== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.

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

    ==14222== All heap blocks were freed -- no leaks
    are possible.


     


      


    2.内存读写越界


    代码如下


     


    #include
    <stdlib.h>

    #include <stdio.h>

    int main(int argc,char argv[])

    {

        int len=5;

        int i;

        int pt=(int)malloc(lensizeof(int));

        int p=pt;

        for(i=0;i<len;i++)

        {p++;}

        p=5;

        printf(“%d”,p);

        return;

    }

    Valgrind提示如下

    ==23045== Invalid write of size 4

    ==23045== at 0 x40050A: main (sample2.c:11)

    ==23045== Address 0 x4C2E044 is 0 bytes after a block of size 20 allocd

    ==23045== at 0 x4A05809: malloc (vg_replace_malloc.c:149)

    ==23045== by 0 x4004DF: main (sample2.c:7)

    ==23045==

    ==23045== Invalid read of size 4

    ==23045== at 0 x400514: main (sample2.c:12)

    ==23045== Address 0 x4C2E044 is 0 bytes after a block of size 20 allocd

    ==23045== at 0 x4A05809: malloc (vg_replace_malloc.c:149)

    ==23045== by 0 x4004DF: main (sample2.c:7)

    5==23045==

    ==23045== ERROR SUMMARY: 2 errors 2 contexts (suppressed: 5 1)

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

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

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

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

    ==23045== checked 66,584 bytes.

    ==23045==

    ==23045== LEAK SUMMARY:

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

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

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

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

    ==23045== Use --leak-check=full to see details of
    leaked memory.


     


      


    3srcdst内存覆盖


    代码如下


    #include
    <stdlib.h>


    #include
    <stdio.h>


    #include
    <string.h>


    int main(int
    argc,char argv[])


    { char x[50];


    int i;


    for(i=0;i<50;i++)


    {x[i]=i;}


    strncpy(x+20,x,20);
    //Good


    strncpy(x+20,x,21);
    //Overlap


    x[39]=’\0’;


    strcpy(x,x+20);
    //Good


    x[39]=40;


    x[40]=’\0’;


    strcpy(x,x+20);
    //Overlap


    return 0;


    }


    Valgrind提示如下


    ==24139== Source
    and destination overlap in strncpy(0 x7FEFFFC09, 0 x7FEFFFBF5, 21)


    ==24139== at
    0 x4A0724F: strncpy (mc_replace_strmem.c:116)


    ==24139== by
    0 x400527: main (sample3.c:10)


    ==24139==


    ==24139== Source
    and destination overlap in strcpy(0 x7FEFFFBE0, 0 x7FEFFFBF4)


    ==24139== at
    0 x4A06E47: strcpy (mc_replace_strmem.c:106)


    ==24139== by
    0 x400555: main (sample3.c:15)


    ==24139==


    ==24139== ERROR
    SUMMARY: 2 errors 2 contexts (suppressed: 5 1)


    ==24139==
    malloc/free: in use at exit: 0 bytes in 0 blocks.


    ==24139==
    malloc/free: 0 allocs, 0 frees, 0 bytes allocated.


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


    ==24139== All heap
    blocks were freed -- no leaks are possible.


    4.动态内存经管错误


    常见的内存分派体式格式分三种:静态存储,栈上分派,堆上分派。全局变量属于静态存储,它们是在编译时就被分派了存储空间,函数内的局部变量属于栈上分派,而最灵活的内存应用体式格式当属堆上分派,也叫做内存动态分派了。常用的内存动态分派函数包含:malloc, alloc, realloc, new等,动态开释函数包含free, 。


    一旦成功申请了动态内存,我们就须要本身对其进行内存经管,而这又是最轻易犯错误的。常见的内存动态经管错误包含:


    l 申请和开释不一致


    因为 C++ 兼容 C,而 C 与 C++ 的内存申请和开释函数是不合的,是以在 C++ 法度中,就有两态内存经管函数。一条不变的规矩就是采取 C 体式格式申请的内存就用 C 体式格式开释;用 C++ 体式格式申请的内存,用 C++ 体式格式开释。也就是用 malloc/alloc/realloc 体式格式申请的内存,用 free 开释;用 new 体式格式申请的内存用 开释。在上述法度中,用 malloc 体式格式申请了内存却用 来开释,固然这在很多景象下不会有题目,但这绝对是潜伏的题目。


    l 申请和开释不匹配


    申请了几许内存,在应用完成后就要开释几许。若是没有开释,或者少开释了就是内存泄漏;多开释了也会产生题目。上述法度中,指针p和pt指向的是同一块内存,却被先后开释两次。


    l 开释后仍然读写


    本质上说,体系会在堆上保护一个动态内存链表,若是被开释,就意味着该块内存可以持续被分派给其他项目组,若是内存被开释后再接见,就可能覆盖其他项目组的信息,这是一种严重的错误,上述法度第16行中就在开释后仍然写这块内存。


    下面的一段法度,就包含了内存动态经管中常见的错误。


    #include
    <stdlib.h>


    #include
    <stdio.h>


    int main(int
    argc,char argv[])


    { char
    p=(char)malloc(10);


    char pt=p;


    int i;


    for(i=0;i<10;i++)


    {p[i]=’z’;}


    p;


    p[1]=’a’;


    free(pt);


    return 0;


    }


    Valgrind提示如下


    ==25811==
    Mismatched free() / / []


    ==25811== at
    0 x4A05130: operator (void) (vg_replace_malloc.c:244)


    ==25811== by
    0 x400654: main (sample4.c:9)


    ==25811== Address
    0 x4C2F030 is 0 bytes inside a block of size 10 allocd


    ==25811== at
    0 x4A05809: malloc (vg_replace_malloc.c:149)


    ==25811== by
    0 x400620: main (sample4.c:4)


    ==25811==


    ==25811== Invalid
    write of size 1


    ==25811== at
    0 x40065D: main (sample4.c:10)


    ==25811== Address
    0 x4C2F031 is 1 bytes inside a block of size 10 freed


    ==25811== at 0 x4A05130:
    operator (void) (vg_replace_malloc.c:244)


    ==25811== by
    0 x400654: main (sample4.c:9)


    ==25811==


    ==25811== Invalid
    free() / / []


    ==25811== at
    0 x4A0541E: free (vg_replace_malloc.c:233)


    ==25811== by
    0 x400668: main (sample4.c:11)


    ==25811== Address
    0 x4C2F030 is 0 bytes inside a block of size 10 freed


    ==25811== at
    0 x4A05130: operator (void) (vg_replace_malloc.c:244)


    ==25811== by
    0 x400654: main (sample4.c:9)


    ==25811==


    ==25811== ERROR
    SUMMARY: 3 errors 3 contexts (suppressed: 5 1)


    ==25811==
    malloc/free: in use at exit: 0 bytes in 0 blocks.


    ==25811==
    malloc/free: 1 allocs, 2 frees, 10 bytes allocated.


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


    ==25811== All heap
    blocks were freed -- no leaks are possible.


    5.内存泄漏


    代码如下


    #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() / / []


    ==19013== at
    0 x4A0541E: free (vg_replace_malloc.c:233)


    ==19013== by
    0 x4004F5: main (sample5.c:8)


    ==19013== Address
    0 x4C2E078 is 0 bytes inside a block of size 20 freed


    ==19013== at
    0 x4A0541E: free (vg_replace_malloc.c:233)


    ==19013== by
    0 x4004EC: main (sample5.c:7)


    ==19013==


    ==19013== ERROR
    SUMMARY: 1 errors 1 contexts (suppressed: 5 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.


    6.不法写/


    代码如下


    int main()


    {


    int i, x;


    x = (int
    )malloc(10sizeof(int));


    for (i=0; i<11;
    i++)


    x[i] = i;


    free(x);


    }


    Valgrind提示如下


    ==21483== Invalid
    write of size 4


    ==21483== at
    0 x4004EA: main (sample6.c:6)


    ==21483== Address
    0 x4C2E058 is 0 bytes after a block of size 40 allocd


    ==21483== at
    0 x4A05809: malloc (vg_replace_malloc.c:149)


    ==21483== by
    0 x4004C9: main (sample6.c:4)


    ==21483==


    ==21483== ERROR
    SUMMARY: 1 errors 1 contexts (suppressed: 5 1)


    ==21483==
    malloc/free: in use at exit: 0 bytes in 0 blocks.


    ==21483==
    malloc/free: 1 allocs, 1 frees, 40 bytes allocated.


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


    ==21483== All heap
    blocks were freed -- no leaks are possible.


    7.无效指针


    代码如下


    #include
    <stdlib.h>


    int main()


    {


    char x =
    malloc(10);


    x[10] = a;


    free(x);


    return 0;


    }


    Valgrind提示如下


    ==15262== Invalid
    write of size 1


    ==15262== at
    0 x4004D6: main (sample7.c:5)


    ==15262== Address
    0 x4C2E03A is 0 bytes after a block of size 10 allocd


    ==15262== at
    0 x4A05809: malloc (vg_replace_malloc.c:149)


    ==15262== by
    0 x4004C9: main (sample7.c:4)


    ==15262==


    ==15262== ERROR
    SUMMARY: 1 errors 1 contexts (suppressed: 5 1)


    ==15262==
    malloc/free: in use at exit: 0 bytes in 0 blocks.


    ==15262==
    malloc/free: 1 allocs, 1 frees, 10 bytes allocated.


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


    ==15262== All heap
    blocks were freed -- no leaks are possible.


    8.反复开释


    代码如下


    #include
    <stdlib.h>


    int main()


    {


    char x =
    malloc(10);


    free(x);


    free(x);


    return 0;


    }


    Valgrind提示如下


    ==15005== Invalid
    free() / / []


    ==15005== at
    0 x4A0541E: free (vg_replace_malloc.c:233)


    ==15005== by
    0 x4004DF: main (sample8.c:6)


    ==15005== Address
    0 x4C2E030 is 0 bytes inside a block of size 10 freed


    ==15005== at
    0 x4A0541E: free (vg_replace_malloc.c:233)


    ==15005== by
    0 x4004D6: main (sample8.c:5)


    ==15005==


    ==15005== ERROR
    SUMMARY: 1 errors 1 contexts (suppressed: 5 1)


    ==15005==
    malloc/free: in use at exit: 0 bytes in 0 blocks.


    ==15005==
    malloc/free: 1 allocs, 2 frees, 10 bytes allocated.


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


    ==15005== All heap
    blocks were freed -- no leaks are possible.


    Valgrind的局限


    l Valgrind不合错误静态数组(分派在栈上)进行鸿沟搜检。若是在法度中声了然一个数组:


    int main()


    {


    char x[10];


    x[11] = a;


    }


    Valgrind则不会警告你,你可以把数组改为动态在堆上分派的数组,如许就可能进行鸿沟搜检了。这个办法如同有点得不偿失的感触感染。


    l Valgrind占用了更多的内存--可达两倍于你法度的正常应用量。若是你用Valgrind来检测应用多量内存的法度就会碰到题目,它可能会用很长的时候来运行测试。大多半景象下,这都不是题目,即使速度慢也仅是检测时速度慢,若是你用Valgrind来检测一个正常运行时速度就很慢的法度,这下题目就大了。 Valgrind不成能检测出你在法度中犯下的所有错误--若是你不搜检缓冲区溢出,Valgrind也不会告诉你代码写了它不该该写的内存。


    附录A:参数指令


    根蒂根基选项:


    这些选项对所有对象都有效。


    -h --help


    显示所有选项的帮助,包含内核和选定的对象两者。


    --help-debug


    和--help雷同,并且还能显示凡是只有Valgrind的开辟人员应用的调试选项。


    --version


    显示Valgrind内核的版本号。对象可以有他们自已的版本号。这是一种包管对象只在它们可以运行的内核上工作的一种设置。如许可以削减在对象和内核之间版本兼容性导致新鲜题目的概率。


    -q --quiet


    安适的运行,只打印错误信息。在进行回归测试或者有其它的主动化测试机制时会很是有效。


    -v --verbose


    显示具体信息。在各个方面显示你的法度的额外信息,例如:共享对象加载,应用的重置,履行引擎和对象的过程,异常行动的警告信息。反复这个标识表记标帜可以增长具体的级别。


    -d


    调试Valgrind自身发出的信息。凡是只有Valgrind开辟人员对此感爱好。反复这个标识表记标帜可以产生更具体的输出。若是你发送一个bug呈报,经由过程-v -v -d -d生成的输出会使你的呈报加倍有效。


    --tool=<toolname>
    [default: memcheck]


    运行toolname指定的Valgrind,例如,Memcheck, Addrcheck, Cachegrind,等等。


    --trace-children=<yes|no>
    [default: no]


    当这个选项打开时,Valgrind会跟踪到子过程中。这经常会导致困惑,并且凡是不是你所期望的,所以默认这个选项是封闭的。


    --track-fds=<yes|no>
    [default: no]


    当这个选项打开时,Valgrind会在退出时打印一个打开文件描述符的列表。每个文件描述符都邑打印出一个文件是在哪里打开的栈回溯,和任何与此文件描述符相干的具体信息比如文件名或socket信息。


    --time-stamp=<yes|no>
    [default: no]


    当这个选项打开时,每条信息之前都有一个从法度开端消失的时候,用天,小时,分钟,秒和毫秒默示。


    --log-fd=<number>
    [default: 2, stderr]


    指定Valgrind把它所有的消息都输出到一个指定的文件描述符中去。默认值2, 是标准错误输出(stderr)。重视这可能会干扰到客户端自身对stderr的应用, Valgrind的输出与客户法度的输出将穿插在一路输出到stderr。


    --log-file=<filename>


    指定Valgrind把它所有的信息输出到指定的文件中。实际上,被创建文件的文件名是由filename、.和过程号连接起来的(即<filename>.<pid>),从而每个过程创建不合的文件。


    --log-file-exactly=<filename>


    类似于--log-file,然则后缀.pid不会被添加。若是设置了这个选项,应用Valgrind跟踪多个过程,可能会获得一个东倒西歪的文件。


    --log-file-qualifier=<VAR>


    当和--log-file一路应用时,日记文件名将经由过程景象变量¥VAR来筛选。这对于MPI法度是有益的。更多的细节,查看手册2.3节 注解。


    --log-socket=<ip-address:port-number>


    指定Valgrind输出所有的消息到指定的IP,指定的端口。当应用1500端口时,端口有可能被忽视。若是不克不及建树一个到指定端口的连接,Valgrind将输出写到标准错误(stderr)。这个选项经常和一个Valgrind法度一路应用。更多的细节,查看手册2.3节 注解。


    错误相干选项:


    这些选项实用于所有产生错误的对象,比如Memcheck, 然则Cachegrind不可。


    --xml=<yes|no>
    [default: no]


    当这个选项打开时,输出将是XML格局。这是为了应用Valgrind的输出做为输入的对象,例如GUI前端加倍轻易些。今朝这个选项只在Memcheck时生效。


    --xml-user-comment=<string>


    在XML开首 附加用户注释,仅在指定了--xml=yes时生效,不然忽视。


    --demangle=<yes|no>
    [default: yes]


    打开/封闭C++的名字主动解码。默认打开。当打开时,Valgrind将测验测验着把编码过的C++名字主动转回初始状况。这个可以处理惩罚g++版本为2.X,3.X或4.X生成的符号。一个关于名字编码解码首要的事实是,禁止文件中的解码函数名仍然应用他们未解码的情势。Valgrind在搜寻可用的禁止条目时不合错误函数名解码,因为这将使禁止文件内容依附于Valgrind的名字解码机制状况,会使速度变慢,且无意义。


    --num-callers=<number>
    [default: 12]


    默认景象下,Valgrind显示12层函数调用的函数名有助于断定法度的地位。可以经由过程这个选项来改变这个数字。如许有助在嵌套调用的层次很深时断定法度的地位。重视错误信息凡是只回溯到最顶上的4个函数。(当前函数,和它的3个调用者的地位)。所以这并不影响呈报的错误总数。这个值的最大值是50。重视高的设置会使Valgrind运行得慢,并且应用更多的内存,然则在嵌套调用层次斗劲高的法度中很是实用。


    --error-limit=<yes|no>
    [default: yes]


    当这个选项打开时,在总量达到10,000,000,或者1,000个不合的错误,Valgrind停止呈报错误。这是为了避免错误跟踪机制在错误很多的法度下变成一个重大的机能肩负。


    --error-exitcode=<number>
    [default: 0]


    指定若是Valgrind在运行过程中呈报任何错误时的退出返回值,有两种景象;当设置为默认值(零)时,Valgrind返回的值将是它模仿运行的法度的返回值。当设置为非零值时,若是Valgrind发明任何错误时则返回这个值。在Valgrind做为一个测试对象套件的项目组应用时这将很是有效,因为使测试对象套件只搜检Valgrind返回值就可以知道哪些测试用例Valgrind呈报了错误。


    --show-below-main=<yes|no>
    [default: no]


    默认地,错误时的栈回溯不显示main()之下的任何函数(或者类似的函数像glibc的__libc_start_main(),若是main()没有呈如今栈回溯中);这些大项目组都是令人厌倦的C库函数。若是打开这个选项,在main()之下的函数也将会显示。


    --suppressions=<filename>
    [default: ¥PREFIX/lib/valgrind/default.supp]


    指定一个额外的文件读取不须要理会的错误;你可以按照须要应用随便率性多的额外文件。


    --gen-suppressions=<yes|no|all>
    [default: no]


    当设置为yes时,Valgrind将会在每个错误显示之后主动暂停并且打印下面这一行:---- Print suppression ? --- [Return/N/n/Y/y/C/c] ----这个提示的行动和--db-attach选项(见下面)雷同。若是选择是,Valgrind会打印出一个错误的禁止条目,你可以把它剪切然后粘帖到一个文件,若是不在将来再看到这个错误信息。当设置为all时,Valgrind会对每一个错误打印一条禁止条目,而不向用户询问。这个选项对C++法度很是有效,它打印出编译器调剂过的名字。重视打印出来的禁止条目是尽可能的特定的。若是须要把类似的条目归纳起来,比如在函数名中添加通配符。并且,有些时辰两个不合的错误也会产生同样的禁止条目,这时Valgrind就会输出禁止条目不止一次,然则在禁止条目标文件中只须要一份拷贝(然则若是多于一份也不会引起什么题目)。并且,禁止条目标名字像<在这儿输入一个禁止条目标名字>;名字并不是很首要,它只是和-v选项一路应用打印出所有应用的禁止条目记录。


    --db-attach=<yes|no>
    [default: no]


    当这个选项打开时,Valgrind将会在每次打印错误时暂停并打出如下一行:---- Attach to
    debugger ? --- [Return/N/n/Y/y/C/c] ---- 按下回车,或者N、回车,n、回车,Valgrind不会对这个错误启动调试器。按下Y、回车,或者y、回车,Valgrind会启动调试器并设定在法度运行的这个点。当调试停止时,退出,法度会持续运行。在调试器内部测验测验持续运行法度,将不会生效。按下C、回车,或者c、回车,Valgrind不会启动一个调试器,并且不会再次询问。重视:--db-attach=yes与--trace-children=yes有冲突。你不克不及同时应用它们。Valgrind在这种景象下不克不及启动。


    2002.05: 这是一个汗青的遗留物,若是这个题目影响到你,请发送邮件并投诉这个题目。


    2002.11:若是你发送输出到日记文件或者到收集端口,我猜这不会让你有任何感触感染。不须理会。


    --db-command=<command>
    [default: gdb -nw %f %p]


    经由过程--db-attach指定如何应用调试器。默认的调试器是gdb.默认的选项是一个运行时扩大Valgrind的模板。 %f会用可履行文件的文件名调换,%p会被可履行文件的过程ID调换。


    这指定了Valgrind将如何调用调试器。默认选项不会因为在机关时是否检测到了GDB而改变,凡是是/usr/bin/gdb.应用这个号令,你可以指定一些调用其它的调试器来调换。


    给出的这个号令字串可以包含一个或多个%p %f扩大。每一个%p实例都被申明成将调试的过程的PID,每一个%f实例都被申明成要调试的过程的可履行文件路径。


    --input-fd=<number>
    [default: 0, stdin]


    应用--db-attach=yes和--gen-suppressions=yes选项,在发明错误时,Valgrind会停下往来交游读取键盘输入。默认地,从标准输入读取,所以封闭了标准输入的法度会有题目。这个选项容许你指定一个文件描述符来调换标准输入读取。


    --max-stackframe=<number>
    [default: 2000000]


    栈的最大值。若是栈指针的偏移跨越这个数量,Valgrind则会认为法度是切换到了别的一个栈履行。若是在法度中有多量的栈分派的数组,你可能须要应用这个选项。valgrind对峙对法度栈指针的追踪。若是栈指针的偏移跨越了这个数量,Valgrind假定你的法度切换到了别的一个栈,并且Memcheck行动与栈指


    针的偏移没有超出这个数量将会不合。凡是这种机制运转得很好。然而,若是你的法度在栈上申请了大的布局,这种机制将会发挥解析得笨拙,并且Memcheck将会呈报多量的不法栈内存接见。这个选项容许把这个阀值设置为其它值。应当只在Valgrind的调试输出中显示须要这么做时才应用这个选项。在这种景象下,它会告诉你应当指定的新的阀值。广泛地,在栈平分派大块的内存是一个坏的主意。因为这很轻易用光你的栈空间,尤其是在内存受限的体系或者支撑多量小客栈的线程的体系上,因为Memcheck履行的错误搜检,对于堆上的数据比对栈上的数据要高效很多。若是你应用这个选项,你可能推敲重写代码在堆上分派内存而不是在栈上分派。


    MALLOC()相干的选项:


    对于应用自有版本的malloc() (例如Memcheck和massif),下面的选项可以应用。


    --alignment=<number>
    [default: 8]


    默认Valgrind的malloc(),realloc(), 等等,是8字节对齐地址的。这是大项目组处理惩罚器的标准。然而,一些法度可能假定malloc()等老是返回16字节或更多对齐的内存。供给的数值必须在8和4096区间之内,并且必须是2的幂数。


    非通用选项:


    这些选项可以用于所有的对象,它们影响Valgrind core的几个特点。大项目组人不会用到这些选项。


    --run-libc-freeres=<yes|no>
    [default: yes]


    GNU C库(libc.so),所有法度共用的,可能会分派一项目组内存自已用。凡是在法度退出时开释内存并不麻烦 -- 这里没什么题目,因为Linux内核在一个过程退出时会收受接管过程全部的资料,所以这只是会造成速度慢。glibc的作者熟悉到如许会导致内存搜检器,像Valgrind,在退出时搜检内存错误的呈报glibc的内存泄目,为了避免这个题目,他们供给了一个__libc_freeres()例程希罕用来让glibc开释分派的所有内存。是以Memcheck在退出时测验测验着去运行__libc_freeres()。不幸的是,在glibc的一些版本中,__libc_freeres是有bug会导致段错误的。这在Red Hat 7.1上有希罕声明。所以,供给这个选项来决意是否运行__libc_freeres。若是你的法度看起来在Valgrind上运行得很好,然则在退出时产生段错误,你可能须要指定--run-libc-freeres=no来批改,这将可能错误的呈报libc.so的内存泄漏。


    --sim-hints=hint1,hint2,...


    传递杂凑的提示给Valgrind,稍微的批改模仿行动的非标准或危险体式格式,可能有助于模仿新鲜的特点。默认没有提示打开。警惕应用!今朝已知的提示有:


    l lax-ioctls: 对ioctl的处理惩罚很是不严格,独一的假定是大小是正确的。不须要在写时缓冲区完全的初始化。没有这个,用多量的新鲜的ioctl号令来应用一些设备驱动将会很是烦人。


    l enable-inner:打开某些特别的结果,当运行的法度是Valgrind自身时。


    --kernel-variant=variant1,variant2,...


    处理惩罚体系调用和ioctls在这个平台的默认核心上产生不合的变量。这有助于运行在改进过的内核或者支撑非标准的ioctls上。警惕应用。若是你不睬解这个选项做的是什么那你几乎不须要它。已经知道的变量有:


    l bproc: 支撑X86平台上的sys_broc体系调用。这是为了运行在BProc,它是标准Linux的一个变种,有时用来构建集群。


    --show-emwarns=<yes|no>
    [default: no]


    当这个选项打开时,Valgrind在一些特定的景象下将对CPU仿真产生警告。凡是这些都是不惹人重视的。


    --smc-check=<none|stack|all>
    [default: stack]


    这个选项把握Valgrind对自我批改的代码的检测。Valgrind可以不做检测,可以检测栈中自我批改的代码,或者随便率性处所检测自我批改的代码。重视默认选项是捕获绝大多半景象,到今朝我们懂得的景象为止。应用all选项时会极大的降落速度。(然则用none选项运行极少影响速度,因为对大多半法度,很是少的代码被添加到栈中)


    调试VALGRIND选项:


    还有一些选项是用来调试Valgrind自身的。在运行一般的器材时不该该须要的。若是你看到选项列表,应用--help-debug选项。


    内存搜检选项:


    --leak-check=<no|summary|yes|full>
    [default: summary]


    当这个选项打开时,当客户法度停止时查找内存泄漏。内存泄漏意味着有效malloc分派内存块,然则没有效free开释,并且没有指针指向这块内存。如许的内存块永远不克不及被法度开释,因为没有指针指向它们。若是设置为summary,Valgrind会呈报有几许内存泄漏产生了。若是设置为full或yes,Valgrind给出每一个自力的泄漏的具体信息。


    --show-reachable=<yes|no>
    [default: no]


    当这个选项封闭时,内存泄漏检测器只显示没有指针指向的内存块,或者只能找到指向块中心的指针。当这个选项打开时,内存泄漏检测器还呈报有指针指向的内存块。这些块是最有可能呈现内存泄漏的处所。你的法度可能,至少在原则上,应当在退出前开释这些内存块。这些有指针指向的内存块和没有指针指向的内存块,或者只有内部指针指向的块,都可能产生内存泄漏,因为实际上没有一个指向块肇端的指针可以拿来开释,即使你想去开释它。


    --leak-resolution=<low|med|high>
    [default: low]


    在做内存泄漏搜检时,断定memcheck将怎么样推敲不合的栈是雷同的景象。当设置为low时,只须要前两层栈匹配就认为是雷同的景象;当设置为med,必必要四层栈匹配,当设置为high时,所有层次的栈都必须匹配。对于hardcore内存泄漏搜检,你很可能须要应用--leak-resolution=high和--num-callers=40或者更大的数字。重视这将产生巨量的信息,这就是为什么默认选项是四个调用者匹配和低辨别率的匹配。重视--leak-resolution= 设置并不影响memcheck查找内存泄漏的才能。它只是改变了成果如何输出。


    --freelist-vol=<number>
    [default: 5000000]


    当客户法度应用free(C中)或者(C++)开释内存时,这些内存并不是即速就可以用来再分派的。这些内存将被标识表记标帜为不成接见的,并被放到一个已开释内存的队列中。如许做的目标是,使开释的内存再次被哄骗的点尽可能的晚。这有利于memcheck在内存块开释后这段首要的时候搜检对块不合法的接见。这个选项指定了队列所能容纳的内存总容量,以字节为单位。默认的值是5000000字节。增大这个数量会增长memcheck应用的内存,但同时也增长了对已开释内存的不法应用的检测概率。


    --workaround-gcc296-bugs=<yes|no>
    [default: no]


    当这个选项打开时,假定读写栈指针以下的一小段间隔是gcc 2.96的bug,并且不呈报为错误。间隔默认为256字节。重视gcc 2.96是一些斗劲老的Linux发行版(RedHat 7.X)的默认编译器,所以你可能须要应用这个选项。若是不是须要请不要应用这个选项,它可能会使一些真正的错误溜掉。一个更好的解决办法是应用较新的,批改了这个bug的gcc/g++版本。


    --partial-loads-ok=<yes|no>
    [default: no]


    把握memcheck如何处理惩罚从地址读取时字长度,字对齐,是以哪些字节是可以寻址的,哪些是不成以寻址的。当设置为yes是,如许的读取并不抛出一个寻址错误。而是从不法地址读取的V字节显示为不决义,接见合法地址仍然是像通俗一样映射到内存。设置为no时,从项目组错误的地址读取与从完全错误的地址读取同样处理惩罚:抛出一个不法地址错误,成果的V字节显示为合法数据。重视这种代码行动是违背ISO C/C++标准,应当被认为是有题目的。若是可能,这种代码应当批改。这个选项应当只是做为一个最后推敲的办法。


    --undef-value-errors=<yes|no>
    [default: yes]


    把握memcheck是否搜检不决义值的危险应用。当设为yes时,Memcheck的行动像Addrcheck, 一个轻量级的内存搜检对象,是Valgrind的一个项目组,它并不搜检不决义值的错误。应用这个选项,若是你不看到不决义值错误。


    CACHEGRIND选项:


    手动指定I1/D1/L2缓冲设备,大小是用字节默示的。这三个必须用逗号隔开,中心没有空格,例如: valgrind --tool=cachegrind --I1=65535,2,64你可以指定一个,两个或三个I1/D1/L2缓冲。若是没有手动指定,每个级别应用通俗体式格式(经由过程CPUID指令获得缓冲设备,若是失败,应用默认值)获得的设备。


    --I1=<size>,<associativity>,<line
    size>


    指定第一级指令缓冲的大小,接洽关系度和行大小。


    --D1=<size>,<associativity>,<line
    size>


    指定第一级数据缓冲的大小,接洽关系度和行大小。


    --L2=<size>,<associativity>,<line
    size>


    指定第二级缓冲的大小,接洽关系度和行大小。


    CALLGRIND选项:


    --heap=<yes|no>
    [default: yes]


    当这个选项打开时,具体的追踪堆的应用景象。封闭这个选项时,massif.pid.txt或massif.pid.html将会很是的简短。


    --heap-admin=<number>
    [default: 8]


    每个块应用的经管字节数。这只能应用一个均匀的估计值,因为它可能变更。glibc应用的分派器每块须要4~15字节,依附于各方面的身分。经管已经开释的块也须要空间,尽管massif不策画这些。


    --stacks=<yes|no>
    [default: yes]


    当打开时,在解析信息中包含栈信息。多线程的法度可能有多个栈。


    --depth=<number>
    [default: 3]


    具体的堆信息中调用过程的深度。增长这个值可以给出更多的信息,然则massif会更使这个法度运行得慢,应用更多的内存,并且产生一个大的massif.pid.txt或者massif.pid.hp文件。


    --alloc-fn=<name>


    指定一个分派内存的函数。这对于应用malloc()的包装函数是有效的,可以用它来填充本来无效的高低文信息。(这些函数会给出无用的高低文信息,并在图中给出无意义的区域)。指定的函数在高低文中被忽视,例如,像对malloc()一样处理惩罚。这个选项可以在号令行中反复多次,指定多个函数。


    --format=<text|html>
    [default: text]


    产生text或者HTML格局的具体堆信息,文件的后缀名应用.txt或者.html。


    HELGRIND选项:


    --private-stacks=<yes|no>
    [default: no]


    假定线程栈是私有的。


    --show-last-access=<yes|some|no>
    [default: no]


    显示最后一次字接见失足的地位。


    LACKEY选项:


    --fnname=<name>
    [default: _dl_runtime_resolve()]


    对<name>函数计数。


    --detailed-counts=<no|yes>
    [default: no]


    对读取,存储和alu操纵计数。


     


    4.3. Explanation of error messages Memcheck


    Despite considerable sophistication under the hood, Memcheck can only really detect two kinds of errors: use of illegal addresses, and use of undefined values. Nevertheless, this is enough to help you discover all sorts of memory-management problems in your code.


    [Valgrind Memcheck仅能检测两种错误,一是不法地址应用,二是不决义值应用。但这足以帮助你搜检出代码中各类类型的内存经管题目。]


    This section presents a quick summary of what error messages mean. The precise behaviour of the error-checking machinery is described in Details of Memchecks checking machinery.






    4.3.1. Illegal read / Illegal write errors [不法读写错误]





    For example:


    Invalid read of size 4
    at 0 x40F6BBCC: (within /usr/lib/libpng.so.2.1.0.9)
    by 0 x40F6B804: (within /usr/lib/libpng.so.2.1.0.9)
    by 0 x40B07FF4: read_png_image(QImageIO ) (kernel/qpngio.cpp:326)
    by 0 x40AC751B: QImageIO::read() (kernel/qimage.cpp:3621)
    Address 0 xBFFFF0E0 is not stackd, mallocd or freed

    This happens when your program reads or writes memory at a place which Memcheck reckons it shouldnt.


    [上方的错误信息默示Memcheck认为你的法度错误的进行了对内存某个地位的读或写操纵。]


    In this example, the program did a 4-byte read at address 0 xBFFFF0E0, somewhere within the system-supplied library libpng.so.2.1.0.9, which was called somewhere else in the same library, called line 326 of qpngio.cpp, and so on.


    [具体信息注解,法度在 0 xBFFFF0E0 处进行了4个字节的读操纵,该操纵产生在体系供给的 libpng.so.2.1.0.9 中,进而显示该库的调用由 qpngio.cpp 文件的 326 行处引起,等等类似描述。]


    Memcheck tries to establish what the illegal address might relate to, since thats often useful. So, if it points into a block of memory which has already been freed, youll be informed of this, and also where the block was freed at. Likewise, if it should turn out to be just off the end of a mallocd block, a common result of off-by-one-errors in array subscripting, youll be informed of this fact, and also where the block was mallocd.


    [Memcheck尽可能地帮助用户指失足误地址与什么有接洽关系,以供给有效信息。例如,若是法度应用了已经被开释的内存块,那么你除了能从Memcheck得知这一景象外,还能获得具体是哪一块内存被开释了。再比如,对于数组处理惩罚中凡是会产生的越界现象,Memcheck 不仅会通知用户这一景象的呈现,还会指出失足地位。]


    In this example, Memcheck cant identify the address. Actually the address is on the stack, but, for some reason, this is not a valid stack address -- it is below the stack pointer and that isnt allowed. In this particular case its probably caused by gcc generating invalid code, a known bug in some ancient versions of gcc.


    [在上方的例子中, Memcheck不克不及断定具体地址。实际上,地址位于栈中,然则因为某些原因,它是一个无效的栈地址。]


    Note that Memcheck only tells you that your program is about to access memory at an illegal address. It cant stop the access happening. So, if your program makes an access which normally would result in a segmentation fault, you program will still suffer the same fate -- but you will get a message Memcheck immediately prior to this. In this particular example, reading junk on the stack is non-fatal, and the program stays alive.


    [重视:Memcheck 只能告诉你你的法度将接见不法地址内存,但它不克不及阻拦接见。所以,若是你的法度接见中导致段错误,那法度将一向带有这个错误,但 Memcheck 会在此产生之前给你提示信息。在上方的例子中,对栈上的垃圾区域进行读操纵没有风险,法度也不会溃散。]







    4.3.2. Use of uninitialised values [值在初始化前应用]





    For example:


    Conditional jump or move depends on uninitialised value(s)
    at 0 x402DFA94: _IO_vfprintf (_itoa.h:49)
    by 0 x402E8476: _IO_printf (printf.c:36)
    by 0 x8048472: main (tests/manuel1.c:8)

    An uninitialised-value use error is reported when your program uses a value which hasnt been initialised -- in other words, is undefined. Here, the undefined value is used somewhere inside the printf() machinery of the C library. This error was reported when running the following small program:


    [未初始值的应用错误,即不决义先应用。如下例:]


    int main()
    {
    int x;
    printf (x = %d\n, x);
    }

    It is important to understand that your program can copy around junk (uninitialised) data as much as it likes.


    [你的法度可以或许对垃圾(未初始)数据进行拷贝,懂得这点很首要。]


    Memcheck observes this and keeps track of the data, but does not complain. A complaint is issued only when your program attempts to make use of uninitialised data. In this example, x is uninitialised. Memcheck observes the value being passed to _IO_printf and thence to _IO_vfprintf, but makes no comment. However, _IO_vfprintf has to examine the value of x so it can turn it into the corresponding ASCII string, and it is at this point that Memcheck complains.


    [Memcheck 调查并跟踪数据,但它临时不会报错。只有当你试图应用未初始的数据时才会报错。在上方的例子中,x 未被初始化,Memcheck 可以或许调查到该值传给 _IO_printf,然后传给 _IO_vfprintf,但此时不报错。而当 _IO_vfprintf 必必要检测 x 的值时,它须要将 x 值转换成响应的 ASCII 码字符串,此时 Memcheck就要报错了。]


    Sources of uninitialised data tend to be:


    [未初始值的起原包含:]





    • Local variables in procedures which have not been initialised, as in the example above.



    • [本地变量在履行过程中未初始化,如上例。]


    • The contents of mallocd blocks, before you write something there. In C++, the new operator is a wrapper round malloc, so if you create an object with new, its fields will be uninitialised until you (or the constructor) fill them in.



    • [malloc分派的块内容未能初始化,希罕是在写入数据之前。在C++中,new 操纵符包含 malloc 操纵,所以,若是你用 new 创建了一个对象,你必须为其指向的内存填充内容,或应用机关函数初始后,才算真正初始化。]








    4.3.3. Illegal frees [不法开释内存]





    For example:


    Invalid free()
    at 0 x4004FFDF: free (vg_clientmalloc.c:577)
    by 0 x80484C7: main (tests/doublefree.c:10)
    Address 0 x3807F7B4 is 0 bytes inside a block of size 177 freed
    at 0 x4004FFDF: free (vg_clientmalloc.c:577)
    by 0 x80484C7: main (tests/doublefree.c:10)

    Memcheck keeps track of the blocks allocated by your program with malloc/new, so it can know exactly whether or not the argument to free/ is legitimate or not. Here, this test program has freed the same block twice. As with the illegal read/write errors, Memcheck attempts to make sense of the address freed. If, as here, the address is one which has previously been freed, you wil be told that -- making duplicate frees of the same block easy to spot.


    [因为Memcheck 可以或许对峙对 malloc/new 分派的块的跟踪,所以,它可以或许确切地知道 free/ 是否合法。这里,可以看到上方测试法度对同一块开释了两次。与处理惩罚不法读写错误一样,Memcheck 试图使 freed 失足地址看起来更有意义。见实例]







    4.3.4. When a block is freed with an inappropriate deallocation function [应用不恰当的开释函数开释块]





    In the following example, a block allocated with new[] has wrongly been deallocated with free:


    [下面的例子显示了应用free() 错误地开释了 new[] 分派的内存:]


    Mismatched free() /  /  []
    at 0 x40043249: free (vg_clientfuncs.c:171)
    by 0 x4102BB4E: QGArray::~QGArray(void) (tools/qgarray.cpp:149)
    by 0 x4C261C41: PptDoc::~PptDoc(void) (include/qmemarray.h:60)
    by 0 x4C261F0E: PptXml::~PptXml(void) (pptxml.cc:44)
    Address 0 x4BB292A8 is 0 bytes inside a block of size 64 allocd
    at 0 x4004318C: operator new[](unsigned int) (vg_clientfuncs.c:152)
    by 0 x4C21BC15: KLaola::readSBStream(int) const (klaola.cc:314)
    by 0 x4C21C155: KLaola::stream(KLaola::OLENode const ) (klaola.cc:416)
    by 0 x4C21788F: OLEFilter::convert(QCString const &) (olefilter.cc:272)

    In C++ its important to deallocate memory in a way compatible with how it was allocated. The deal is:


    [C++中,以正确的体式格式开释内存很是首要,具体如下:]





    • If allocated with malloc, calloc, realloc, valloc or memalign, you must deallocate with free.



    • [若是内存应用 malloc\calloc\realloc\valloc\memalign 分派,你必须应用 free 开释。]


    • If allocated with new[], you must deallocate with [].



    • [若是应用 new[] 分派,你必须应用 [] 开释。]


    • If allocated with new, you must deallocate with .



    • [若是应用 new 分派,你必须应用 开释。]



    The worst thing is that on Linux apparently it doesnt matter if you do mix these up, but the same program may then crash on a different platform, Solaris for example. So its best to fix it properly. According to the KDE folks its amazing how many C++ programmers dont know this.


    [最糟糕的是,若是搞混,有时在 Linux 平台不会失足,但在其他平台,如 Solaris 却会使法度溃散。所以,好还是批改法度,恰当应用每种体式格式。也不怪 KDE 的开辟者们在赞叹“怎么会有那么多法度员不知道这一点。”]


    The reason behind the requirement is as follows. In some C++ implementations, [] must be used for objects allocated by new[] because the compiler stores the size of the array and the pointer-to-member to the destructor of the arrays content just before the pointer actually returned. This implies a variable-sized overhead in whats returned by new or new[].







    4.3.5. Passing system call parameters with inadequate read/write permissions [传递体系调用参数时读写权限不足]





    Memcheck checks all parameters to system calls:





    • It checks all the direct parameters themselves.



    • [搜检直接参数]


    • Also, if a system call needs to read a buffer provided by your program, Memcheck checks that the entire buffer is addressable and has valid data, ie, it is readable.



    • [法度供给缓冲区参数]


    • Also, if the system call needs to write to a user-supplied buffer, Memcheck checks that the buffer is addressable.



    • [用户供给缓冲区参数]



    After the system call, Memcheck s its tracked information to precisely reflect any changes in memory permissions caused by the system call.


    Heres an example of two system calls with invalid parameters:


    #include <stdlib.h>
    #include <unistd.h>
    int main( void )
    {
    char arr = malloc(10);
    int arr2 = malloc(sizeof(int));
    write( 1 / stdout /, arr, 10 );
    exit(arr2[0]);
    }

    You get these complaints ...


    Syscall param write(buf) points to uninitialised byte(s)
    at 0 x25A48723: __write_nocancel (in /lib/tls/libc-2.3.3.so)
    by 0 x259AFAD3: __libc_start_main (in /lib/tls/libc-2.3.3.so)
    by 0 x8048348: (within /auto/homes/njn25/grind/head4/a.out)
    Address 0 x25AB8028 is 0 bytes inside a block of size 10 allocd
    at 0 x259852B0: malloc (vg_replace_malloc.c:130)
    by 0 x80483F1: main (a.c:5)

    Syscall param exit(error_code) contains uninitialised byte(s)
    at 0 x25A21B44: __GI__exit (in /lib/tls/libc-2.3.3.so)
    by 0 x8048426: main (a.c:8)

    ... because the program has (a) tried to write uninitialised junk the mallocd block to the standard output, and (b) passed an uninitialised value to exit. Note that the first error refers to the memory pointed to by buf (not buf itself), but the second error refers directly to exits argument arr2[0].







    4.3.6. Overlapping source and destination blocks [泉源和目标块重叠]





    The following C library functions copy some data one memory block to another (or something similar): memcpy(), strcpy(), strncpy(), strcat(), strncat(). The blocks pointed to by their src and dst pointers arent allowed to overlap. Memcheck checks for this.


    [C库中一些具有拷贝功能的函数,如memcpy(), strcpy(), strncpy(), strcat(), strncat(),他们将数据从一个内存块中拷贝至另一个中。泉源和目标内存块不容许有重叠, Memcheck 可以搜检这种错误。]


    For example:


    ==27492== Source and destination overlap in memcpy(0 xbffff294, 0 xbffff280, 21)
    ==27492== at 0 x40026CDC: memcpy (mc_replace_strmem.c:71)
    ==27492== by 0 x804865A: main (overlap.c:40)

    You dont want the two blocks to overlap because one of them could get partially overwritten by the copying.


    You might think that Memcheck is being overly pedantic reporting this in the case where dst is less than src. For example, the obvious way to implement memcpy() is by copying the first byte to the last. However, the optimisation guides of some architectures recommend copying the last byte down to the first. Also, some implementations of memcpy() zero dst before copying, because zeroing the destinations cache line(s) can improve performance.


    In addition, for many of these functions, the POSIX standards have wording along the lines If copying takes place between objects that overlap, the behavior is undefined. Hence overlapping copies violate the standard.


    The moral of the story is: if you want to write truly portable code, dont make any assumptions about the language implementation.







    4.3.7. Memory leak detection [内存漏洞检测]





    Memcheck keeps track of all memory blocks issued in response to calls to malloc/calloc/realloc/new. So when the program exits, it knows which blocks have not been freed.


    [Memcheck 对峙对所有 malloc/calloc/realloc/new 分派的内存块的跟踪,是以当法度退出时,它能检测出哪一块未被开释。]


    If --leak-check is set appropriately, for each remaining block, Memcheck scans the entire address space of the process, looking for pointers to the block. Each block fits into one of the three following categories.


    [若是 --leak-check 被设置,则 Memcheck 将扫描全部空间地址,寻找指向块的指针。处理惩罚后,在 Memcheck 中可以将块分类三类:]





    • Still reachable: A pointer to the start of the block is found. This usually indicates programming sloppiness. Since the block is still pointed at, the programmer could, at least in principle, free it before program exit. Because these are very common and arguably not a problem, Memcheck wont report such blocks unless --show-reachable=yes is specified.



    • [仍可被接见的块:存在一个指针指向该块的肇端地位。这凡是注解编程程度太潮。因为法度退出后法度员至少要将内存开释掉,而不该再有指针指向它。Memcheck 凡是不会呈报此类题目,除非你应用了 --show-reachable=yes 选项,因为这些题目很常见且存有争议。]


    • Possibly lost, or dubious: A pointer to the interior of the block is found. The pointer might originally have pointed to the start and have been moved along, or it might be entirely unrelated. Memcheck deems such a block as dubious, because its unclear whether or not a pointer to it still exists.



    • [可能丧失或“有疑问的块”:指向块内部的指针被发明。该指针很可能开端时指向块首,后来被移动,或者终极没有任何接洽关系。 Memcheck 认为如许的块为“有疑问的块”,因为不清楚是否还有指针指向它。]


    • Definitely lost, or leaked: The worst outcome is that no pointer to the block can be found. The block is classified as leaked, because the programmer could not possibly have freed it at program exit, since no pointer to it exists. This is likely a symptom of having lost the pointer at some earlier point in the program.



    • [明显丧失或“内存泄漏”:最坏的成果是某些块已没有指针指向,却还能被发明。如许的块被归入“泄漏”类,是因为法度员在法度终止时没有开释,因为没有指针指向他们。这很象法度运行前期指针丧失的症状。]



    For each block mentioned, Memcheck will also tell you where the block was allocated. It cannot tell you how or why the pointer to a leaked block has been lost; you have to work that out for yourself. In general, you should attempt to ensure your programs do not have any leaked or dubious blocks at exit.


    [对以上每种景象,Memcheck 都邑告诉你该块在何处被分派。但它不会告诉你如何和为什么指向该块的指针丧失。你必须本身进一步断定。总起来说,你应当起首确保法度在退出时不会有任何泄漏或有泄漏偏向的块存在。]


    For example:


    8 bytes in 1 blocks are definitely lost in loss record 1 of 14
    at 0 x........: malloc (vg_replace_malloc.c:...)
    by 0 x........: mk (leak-tree.c:11)
    by 0 x........: main (leak-tree.c:39)

    88 (8 direct, 80 indirect) bytes in 1 blocks are definitely lost
    in loss record 13 of 14
    at 0 x........: malloc (vg_replace_malloc.c:...)
    by 0 x........: mk (leak-tree.c:11)
    by 0 x........: main (leak-tree.c:25)

    The first message describes a simple case of a single 8 byte block that has been definitely lost. The second case mentions both direct and indirect leaks. The distinction is that a direct leak is a block which has no pointers to it. An indirect leak is a block which is only pointed to by other leaked blocks. Both kinds of leak are bad.


    [第一项目组描述了有8字节块明白丧失,第二项目组提到了“直接”和“间接”泄漏,其差别是直接泄漏为存在一个内存块,而没有指针指向它。间接泄漏则为存在一个块,而存有其他泄漏块指向该块。两种景象都不是功德。]


    The precise area of memory in which Memcheck searches for pointers is: all naturally-aligned machine-word-sized words found in memory that Memchecks records indicate is both accessible and initialised.


    [以上提到的 Memcheck用于寻找指针的内存块的确切区域指的是:内存中所有能过找到的天然接洽关系的、按机械字长度策画的 words, 以上所指内存是指 Memcheck 记录中注解可被接见和可被初始化的内存区域。]

    分享到: