zoukankan      html  css  js  c++  java
  • glibc提供的malloc()的调试工具

     关键词:MALLOC_CHECK_、mtrace()、muntrace()、MALLOC_TRACE、mprobe()、-lmcheck等等。

    1. MALLOC_CHECK_环境变量(double free)

    MALLOC_CHECK_提供了类似于mcheck()和mprobe()函数的功能,但是无需对程序进行修改和重新编译。

    设置不同整数值可以控制程序对内存分配错误的响应方式。

    0 - 不产生错误信息,也不中止这个程序

    1 - 产生错误信息,但是不中止这个程序

    2 - 不产生错误信息,但是中止这个程序

    3 - 产生错误信息,并中止这个程序

    下面构造一个double free的错误程序验证一下:

    #include <stdio.h>
    #include <malloc.h>
    
    void main(void)
    {
        char *s = NULL;
    
        s = malloc(32);
        free(s);
        free(s);
    }

    env MALLOC_CHECK_=0 ./dfree的效果类似于直接执行./dfree。

    env MALLOC_CHECK_=1 ./dfree产生如下的错误信息:

    *** Error in `./dfree': free(): invalid pointer: 0x0000000000e22010 ***

    env MALLOC_CHECK_=2 ./dfree简单的终止程序,生成coredump文件。

    Aborted (core dumped)

    通过分析core文件,然后bt full查看backtrace:

    (gdb) bt full
    #0  0x00007fb4cd69c428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
            resultvar = 0
            pid = 3415
            selftid = 3415
    #1  0x00007fb4cd69e02a in __GI_abort () at abort.c:89
            save_stage = 2
            act = {__sigaction_handler = {sa_handler = 0x0, sa_sigaction = 0x0}, sa_mask = {__val = {0 <repeats 14 times>, 1095216660480, 0}}, sa_flags = 0, sa_restorer = 0x0}
            sigs = {__val = {32, 0 <repeats 15 times>}}
    #2  0x00007fb4cd6e6430 in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>, str=<optimized out>, action=<optimized out>) at malloc.c:5010
    No locals.
    #3  free_check (mem=<optimized out>, caller=<optimized out>) at hooks.c:314
    No locals.
    #4  0x00007fb4cd6eb5e7 in __GI___libc_free (mem=<optimized out>) at malloc.c:2942
            ar_ptr = <optimized out>
            p = <optimized out>
            hook = <optimized out>
    #5  0x000000000040059c in main ()
    No symbol table info available.

    env MALLOC_CHECK_=3 ./dfree显示更多的信息并且coredump。

    *** Error in `./dfree': free(): invalid pointer: 0x0000000000aa0010 ***
    ======= Backtrace: =========--------------------------------------------------------------------问题点的backtrace。
    /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f640d3447e5]
    /lib/x86_64-linux-gnu/libc.so.6(+0x7f72a)[0x7f640d34c72a]
    /lib/x86_64-linux-gnu/libc.so.6(cfree+0xf7)[0x7f640d3515e7]
    ./dfree[0x40059c]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f640d2ed830]
    ./dfree[0x400499]
    ======= Memory map: ========---------------------------------------------------------------------当前进程的maps。
    00400000-00401000 r-xp 00000000 08:11 33178794                           /home/al/test/dfree
    00600000-00601000 r--p 00000000 08:11 33178794                           /home/al/test/dfree
    00601000-00602000 rw-p 00001000 08:11 33178794                           /home/al/test/dfree
    00aa0000-00ac1000 rw-p 00000000 00:00 0                                  [heap]
    7f640d0b7000-7f640d0cd000 r-xp 00000000 08:02 4199205                    /lib/x86_64-linux-gnu/libgcc_s.so.1
    7f640d0cd000-7f640d2cc000 ---p 00016000 08:02 4199205                    /lib/x86_64-linux-gnu/libgcc_s.so.1
    7f640d2cc000-7f640d2cd000 rw-p 00015000 08:02 4199205                    /lib/x86_64-linux-gnu/libgcc_s.so.1
    7f640d2cd000-7f640d48d000 r-xp 00000000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7f640d48d000-7f640d68d000 ---p 001c0000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7f640d68d000-7f640d691000 r--p 001c0000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7f640d691000-7f640d693000 rw-p 001c4000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7f640d693000-7f640d697000 rw-p 00000000 00:00 0 
    7f640d697000-7f640d6bd000 r-xp 00000000 08:02 4199139                    /lib/x86_64-linux-gnu/ld-2.23.so
    7f640d890000-7f640d893000 rw-p 00000000 00:00 0 
    7f640d8bb000-7f640d8bc000 rw-p 00000000 00:00 0 
    7f640d8bc000-7f640d8bd000 r--p 00025000 08:02 4199139                    /lib/x86_64-linux-gnu/ld-2.23.so
    7f640d8bd000-7f640d8be000 rw-p 00026000 08:02 4199139                    /lib/x86_64-linux-gnu/ld-2.23.so
    7f640d8be000-7f640d8bf000 rw-p 00000000 00:00 0 
    7ffc0fb27000-7ffc0fb49000 rw-p 00000000 00:00 0                          [stack]
    7ffc0fbb2000-7ffc0fbb5000 r--p 00000000 00:00 0                          [vvar]
    7ffc0fbb5000-7ffc0fbb7000 r-xp 00000000 00:00 0                          [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
    Aborted (core dumped)

    下面是详细的栈信息:

    #0  0x00007f640d302428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
            resultvar = 0
            pid = 3542
            selftid = 3542
    #1  0x00007f640d30402a in __GI_abort () at abort.c:89
            save_stage = 2
            act = {__sigaction_handler = {sa_handler = 0x2070782d72203030, sa_sigaction = 0x2070782d72203030}, sa_mask = {__val = {3472328296227680304, 3467824696768081952, 2314885530818453536, 2314885530818453536, 
                  7166204968890474528, 3544385727815773281, 4048771456345059427, 4123381033782620218, 2314885530819966513, 2314885530818453536, 3395749441387372576, 6860733171187738988, 8679965255892022326, 7091318039360988973, 
                  8299627453906824547, 7219327610922666607}}, sa_flags = 808532278, sa_restorer = 0x48}
            sigs = {__val = {32, 0 <repeats 15 times>}}
    #2  0x00007f640d3447ea in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7f640d45ded8 "*** Error in `%s': %s: 0x%s ***
    ") at ../sysdeps/posix/libc_fatal.c:175
            ap = <error reading variable ap (Attempt to dereference a generic pointer.)>
            fd = 3
            on_2 = <optimized out>
            list = <optimized out>
            nlist = <optimized out>
            cp = <optimized out>
            written = <optimized out>
    #3  0x00007f640d34c72a in malloc_printerr (ar_ptr=0x7f640d691b20 <main_arena>, ptr=<optimized out>, str=0x7f640d45acaf "free(): invalid pointer", action=<optimized out>) at malloc.c:5006
            buf = "0000000000aa0010"
            cp = <optimized out>
            ar_ptr = 0x7f640d691b20 <main_arena>
            ptr = <optimized out>
            str = 0x7f640d45acaf "free(): invalid pointer"
            action = <optimized out>
    #4  free_check (mem=<optimized out>, caller=<optimized out>) at hooks.c:314
    No locals.
    #5  0x00007f640d3515e7 in __GI___libc_free (mem=<optimized out>) at malloc.c:2942
            ar_ptr = <optimized out>
            p = <optimized out>
            hook = <optimized out>
    #6  0x000000000040059c in main ()
    No symbol table info available.

    2. mtrace/muntrace/MALLOC_TRACE(重复释放、泄漏)

    mtrace()和muntrace()函数分别在程序中打开和关闭对内存分配调用进行跟踪的功能。

    这两个函数要与环境变量MALLOC_TRACE搭配使用,该变量定义了写入跟踪信息的文件名。

    2.1 构造测试用例

    构造malloc()但是不释放的场景:

    #include <stdlib.h>
    #include <stdio.h>
    #include <mcheck.h>
    
    int main(int argc, char **argv)
    {
            mtrace();
    
            char * p = malloc(100);
            free(p);
    
            p = malloc(1000);
    
            muntrace();
    
            return 0;
    }

    2.2 mtrace()跟踪结果分析

    gcc mtrace.c -o mtrace -g编译带调试信息。

    export MALLOC_TRACE=/home/al/test/mtrace.log设置mtrace()信息输出路径。

    然后执行./mtrace,就会在MALLOC_TRACE下生成malloc()/free()轨迹信息。

    = Start
    @ ./mtrace:[0x400624] + 0x10b4450 0x64
    @ ./mtrace:[0x400634] - 0x10b4450
    @ ./mtrace:[0x40063e] + 0x10b44c0 0x3e8
    = End

    上面的信息格式为:@ 程序名称:[内存分配释放调用的地址] +/- 操作的内存地址 参数

    +表示malloc,-表示free。

    或者如下类型log:

    @ 程序名称:(函数名称+偏移量) [内存分配释放调用地址] +/-/</> 操作内存地址 参数

    +:对应一个malloc()操作。

    -:对应一个free()操作。

    </>:对应一个realloc()操作,成对出现。<表示释放之前内存,>表示申请后结果。如果realloc()的内存第一次申请,那么就对应一个+号。

    @ /usr/lib/libglib-2.0.so.0:(g_malloc+0x2a)[0x2ac7c412] + 0x2b510f50 0x3------------------------g_malloc()中申请0x3字节大小内存,返回地址为0x2b510f50。
    @ /usr/lib/libglib-2.0.so.0:(g_realloc+0x38)[0x2ac7c4cc] + 0x2b510f60 0x20----------------------g_realloc()指针之前没有对应内存,所以对应+。表示申请0x20字节大小内存,返回地址为0x2b510f60。
    @ /usr/lib/libglib-2.0.so.0:(g_free+0x20)[0x2ac7c524] - 0x2b510f40
    @ /usr/lib/libglib-2.0.so.0:(g_malloc+0x2a)[0x2ac7c412] + 0x2b510f40 0xc------------------------在g_malloc()中申请0xc字节大小内存,返回地址为0x2b510f40.
    @ /usr/lib/libglib-2.0.so.0:(g_malloc+0x2a)[0x2ac7c412] + 0x2b510f88 0xc
    @ /usr/lib/libglib-2.0.so.0:(g_realloc+0x38)[0x2ac7c4cc] < 0x2b510f60---------------------------g_realloc()对应的内存已经存在,所以先释放0x2b510f60内存。
    @ /usr/lib/libglib-2.0.so.0:(g_realloc+0x38)[0x2ac7c4cc] > 0x2b510f98 0x40----------------------然后重新申请0x40大小的内存,返回地址为0x2b50f98.
    @ /usr/lib/libglib-2.0.so.0:(g_free+0x20)[0x2ac7c524] - 0x2b510f40------------------------------在g_free()中释放地址为0x2b510f40的内存。
    @ /usr/lib/libglib-2.0.so.0:(g_realloc+0x38)[0x2ac7c4cc] < 0x2b510f98---------------------------g_realoc()对应内存已经存在,释放0x2b510f98对应内存。
    @ /usr/lib/libglib-2.0.so.0:(g_realloc+0x38)[0x2ac7c4cc] > 0x2b513660 0x80----------------------然后重新申请0x80大小内存,返回地址为0x2b513660。

    通过mtrace mtrace mtrace.log可以可读性更强的信息。第一个mtrace是解析mtrace.log的工具,第二个mtrace是测试程序。

    Memory not freed:
    -----------------
               Address     Size     Caller
    0x00000000010b44c0    0x3e8  at /home/al/test/mtrace.c:13

    这里面对过滤掉正常malloc()/free()信息,留下的是泄漏内存。

    Address表示泄漏地址,Size表示泄漏大小,Caller表示泄漏点代码位置。

    2.3 重复释放问题

    如下是重复释放问题,mtrace()会如何处理呢?

    #include <stdio.h>
    #include <malloc.h>
    #include <mcheck.h>
    
    void main(void)
    {
        char *s = NULL;
        mtrace();
        s = malloc(32);
        free(s);
        free(s);
        muntrace();
    }

    执行./dfree结果如下:

    *** Error in `./dfree': double free or corruption (fasttop): 0x000000000188b450 ***

    2.4 mtrace输出解释

    mtrace输出结果还有一些可能不是异常的提示。

    = Start
     [0x8048209] - 0x8064cc8
     [0x8048209] - 0x8064ce0
     [0x8048209] - 0x8064cf8
     [0x80481eb] + 0x8064c48 0x14
     [0x80481eb] + 0x8064c60 0x14
     [0x80481eb] + 0x8064c78 0x14
     [0x80481eb] + 0x8064c90 0x14
    = End

    输出结果如下:

    - 0x08064cc8 Free 2 was never alloc'd /home/drepper/tst.c:39
    - 0x08064ce0 Free 3 was never alloc'd /home/drepper/tst.c:39
    - 0x08064cf8 Free 4 was never alloc'd /home/drepper/tst.c:39
    (-表示free异常) (free内存对应指针) Free (在原log中的行号) was never alloc'd (free函数调用点) Memory not freed: ----------------- Address Size Caller 0x08064c48 0x14 at /home/drepper/tst.c:33 0x08064c60 0x14 at /home/drepper/tst.c:33 0x08064c78 0x14 at /home/drepper/tst.c:33 0x08064c90 0x14 at /home/drepper/tst.c:33

    参考资料:《3.2.4.4 Interpreting the traces》。

    - 0x000000000002ba00 Realloc 1109 was never alloc'd 0x2af654bc
    (-表示释放) (free对应内存地址) Realloc (在log中行号) was never alloc'd (free释放点)

    realloc()首先释放然后重新申请内存,表示在realloc()释放内存的时候没有找到对应的alloc()。

    + 0x000000000006ea48 Alloc 17136 duplicate: 0x2b2ef800 /lib/libstdc++.so.6:(_Znwj+0x24)[0x2b2ef800]
    (+表示alloc()) (alloc()内存地址) Alloc (在log中行号) duplicate: (alloc()调用点)

    表示两次alloc两次,申请的内存地址是一样的。前一次alloc()到本次alloc()之间没有free。

    3. mcheck()检查内存一致性(重复释放、越界)

    mcheck()函数允许程序对已分配内存块进行一致性检查。

    3.1 mcheck()介绍

    #include <mcheck.h>
    
    int mcheck(void (*abortfunc)(enum mcheck_status mstatus));

    调用该函数后,后续内存分配、释放都将进行内存连续性检查,并在内存连续性检查失败后,调用abortfunc。

    枚举体mcheck_status如下:

    enum mcheck_status
      {
        MCHECK_DISABLED = -1,       /* Consistency checking is not turned on.  */
        MCHECK_OK,                  /* Block is fine.  */
        MCHECK_FREE,                /* Block freed twice.  */
        MCHECK_HEAD,                /* Memory before the block was clobbered.  */
        MCHECK_TAIL                 /* Memory after the block was clobbered.  */
      };

    3.2 mcheck()实例

    下例创建捕获错误函数abortfun(),三种你错误类型:重复释放、头覆盖、尾覆盖。

    #include <stdio.h>
    #include <malloc.h>
    #include <mcheck.h>
    #include <errno.h>
    #include <string.h>
    
    void abortfun(enum mcheck_status mstatus)
    {
        if(mstatus == MCHECK_FREE)
            fprintf(stderr, "Block freed twice.
    ");
        else if(mstatus == MCHECK_HEAD)
            fprintf(stderr, "Memory before the block was clobbered.
    ");
        else if(mstatus == MCHECK_TAIL)
            fprintf(stderr, "Memory after the block was clobbered.
    ");
        else
            fprintf(stderr, "Block is fine.
    ");
    }
    
    void main(void)
    {
        char *s = NULL;
    
        if(mcheck(abortfun) != 0)
        {
            fprintf(stderr, "mcheck:%s
    ", strerror(errno));
            return;
        }
        s = malloc(32);
        *(s-1) = 3;--------------------------头覆盖。
        *(s+32) = 3;-------------------------尾覆盖。
        free(s);
        free(s);-----------------------------重复释放。
    }

    执行后结果如下,捕获到了尾覆盖和重复释放,头覆盖没有捕获到;但是单独头覆盖是可以捕获到的。

    并且产生了coredump文件。

    Memory after the block was clobbered.
    Block freed twice.
    *** Error in `./dfree': double free or corruption (fasttop): 0x0000000000957030 ***
    ======= Backtrace: =========
    /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fc2eac267e5]
    /lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fc2eac2f37a]
    /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fc2eac3353c]
    /lib/x86_64-linux-gnu/libc.so.6(+0x87fa0)[0x7fc2eac36fa0]
    /lib/x86_64-linux-gnu/libc.so.6(cfree+0xf7)[0x7fc2eac335e7]
    ./dfree[0x40084a]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fc2eabcf830]
    ./dfree[0x400659]
    ======= Memory map: ========
    00400000-00401000 r-xp 00000000 08:11 33173251                           /home/al/test/dfree
    00600000-00601000 r--p 00000000 08:11 33173251                           /home/al/test/dfree
    00601000-00602000 rw-p 00001000 08:11 33173251                           /home/al/test/dfree
    00957000-00978000 rw-p 00000000 00:00 0                                  [heap]
    7fc2e4000000-7fc2e4021000 rw-p 00000000 00:00 0 
    7fc2e4021000-7fc2e8000000 ---p 00000000 00:00 0 
    7fc2ea999000-7fc2ea9af000 r-xp 00000000 08:02 4199205                    /lib/x86_64-linux-gnu/libgcc_s.so.1
    7fc2ea9af000-7fc2eabae000 ---p 00016000 08:02 4199205                    /lib/x86_64-linux-gnu/libgcc_s.so.1
    7fc2eabae000-7fc2eabaf000 rw-p 00015000 08:02 4199205                    /lib/x86_64-linux-gnu/libgcc_s.so.1
    7fc2eabaf000-7fc2ead6f000 r-xp 00000000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7fc2ead6f000-7fc2eaf6f000 ---p 001c0000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7fc2eaf6f000-7fc2eaf73000 r--p 001c0000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7fc2eaf73000-7fc2eaf75000 rw-p 001c4000 08:02 4199167                    /lib/x86_64-linux-gnu/libc-2.23.so
    7fc2eaf75000-7fc2eaf79000 rw-p 00000000 00:00 0 
    7fc2eaf79000-7fc2eaf9f000 r-xp 00000000 08:02 4199139                    /lib/x86_64-linux-gnu/ld-2.23.so
    7fc2eb172000-7fc2eb175000 rw-p 00000000 00:00 0 
    7fc2eb19d000-7fc2eb19e000 rw-p 00000000 00:00 0 
    7fc2eb19e000-7fc2eb19f000 r--p 00025000 08:02 4199139                    /lib/x86_64-linux-gnu/ld-2.23.so
    7fc2eb19f000-7fc2eb1a0000 rw-p 00026000 08:02 4199139                    /lib/x86_64-linux-gnu/ld-2.23.so
    7fc2eb1a0000-7fc2eb1a1000 rw-p 00000000 00:00 0 
    7ffcc5840000-7ffcc5862000 rw-p 00000000 00:00 0                          [stack]
    7ffcc58df000-7ffcc58e2000 r--p 00000000 00:00 0                          [vvar]
    7ffcc58e2000-7ffcc58e4000 r-xp 00000000 00:00 0                          [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
    Aborted (core dumped)

    4. mprobe()

    函数格式介绍:

    #include <mcheck.h>
    
    enum mcheck_status mprobe(void *ptr);

    mprobe()示例:

    #include <stdio.h>
    #include <malloc.h>
    #include <mcheck.h>
    #include <errno.h>
    #include <string.h>
    
    void abortfun(enum mcheck_status mstatus)
    {
        if(mstatus == MCHECK_FREE)
            fprintf(stderr, "Block freed twice.
    ");
        else if(mstatus == MCHECK_HEAD)
            fprintf(stderr, "Memory before the block was clobbered.
    ");
        else if(mstatus == MCHECK_TAIL)
            fprintf(stderr, "Memory after the block was clobbered.
    ");
        else
            fprintf(stderr, "Block is fine.
    ");
    }
    
    void main(void)
    {
        char *s = NULL;
    
        if(mcheck(abortfun) != 0)
        {
            fprintf(stderr, "mcheck:%s
    ", strerror(errno));
            return;
        }
        s = malloc(32);
        mprobe(s);------------------------------正确
        mprobe(s-1);----------------------------错误,返回MCHECK_HEAD错误类型。
        mprobe(s+32);---------------------------错误,返回MCHECK_HEAD错误类型。
        free(s);
    }

    返回结果:

    Memory before the block was clobbered.
    Memory before the block was clobbered.

    5. -lmcheck自动开启检查

    在编译的时候加上-lmcheck,不需要修改代码就可以对malloc()/free()进行检查。

    #include <stdio.h>
    #include <malloc.h>
    
    void main(void)
    {
        char *s = NULL;
    
        s = malloc(32);
        free(s);
        free(s);
    }

    gcc dfree.c -o dfree -lmcheck编译后,执行./dfree。

    block freed twice
    Aborted (core dumped)

    查看coredump bt full如下:

    #0  0x00007fdf1e826428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
            resultvar = 0
            pid = 5719
            selftid = 5719
    #1  0x00007fdf1e82802a in __GI_abort () at abort.c:89
            save_stage = 2
            act = {__sigaction_handler = {sa_handler = 0x3065383363666637, sa_sigaction = 0x3065383363666637}, sa_mask = {__val = {8659703141076316208, 3472328296227676272, 3472339291342909488, 2314885530818457632, 
                  2314885530818453536, 2314885530818453536, 8314900945785856032, 7378697629477789039, 3472335126135203430, 7378697628523966512, 3474076752553600614, 8659703141076316209, 3472328296227676272, 3472339291342909488, 
                  2314885530818457632, 2314885530818453536}}, sa_flags = 538976288, sa_restorer = 0x54}
            sigs = {__val = {32, 0 <repeats 15 times>}}
    #2  0x00007fdf1e8687ea in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7fdf1e981ed8 "*** Error in `%s': %s: 0x%s ***
    ") at ../sysdeps/posix/libc_fatal.c:175
            ap = <error reading variable ap (Attempt to dereference a generic pointer.)>
            fd = 3
            on_2 = <optimized out>
            list = <optimized out>
            nlist = <optimized out>
            cp = <optimized out>
            written = <optimized out>
    #3  0x00007fdf1e87137a in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>, str=0x7fdf1e981fa0 "double free or corruption (fasttop)", action=3) at malloc.c:5006
            buf = "000000000186a010"
            cp = <optimized out>
            ar_ptr = <optimized out>
            str = 0x7fdf1e981fa0 "double free or corruption (fasttop)"
            action = 3
    #4  _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3867
            size = <optimized out>
            fb = <optimized out>
            nextchunk = <optimized out>
            nextsize = <optimized out>
            nextinuse = <optimized out>
            prevsize = <optimized out>
            bck = <optimized out>
            fwd = <optimized out>
            errstr = <optimized out>
            locked = <optimized out>
    #5  0x00007fdf1e87553c in __GI___libc_free (mem=<optimized out>) at malloc.c:2968
            ar_ptr = <optimized out>
            p = <optimized out>
            hook = <optimized out>
    #6  0x000000000040059c in register_tm_clones ()
    No symbol table info available.
    #7  0x00007ffc38dc54c0 in ?? ()
    No symbol table info available.
    #8  0x000000000186a010 in ?? ()
    No symbol table info available.
    #9  0x00000000004005a0 in register_tm_clones ()
    No symbol table info available.
    #10 0x00007fdf1e811830 in __libc_start_main (main=0x400566 <deregister_tm_clones+54>, argc=1, argv=0x7ffc38dc54c8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffc38dc54b8)
        at ../csu/libc-start.c:291
            result = <optimized out>
            unwind_buf = {cancel_jmp_buf = {{jmp_buf = {0, 4770583698588052314, 4195440, 140721262449856, 0, 0, -4770167831151236262, -4788811728122270886}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x400610 <main+26>, 
                  0x7fdf1ebcbab0 <_dl_fini>}, data = {prev = 0x0, cleanup = 0x0, canceltype = 4195856}}}
            not_first_call = <optimized out>
    #11 0x0000000000400499 in ?? ()
    No symbol table info available.
    #12 0x00007ffc38dc54b8 in ?? ()
    No symbol table info available.
    #13 0x000000000000001c in ?? ()
    No symbol table info available.
    #14 0x0000000000000001 in ?? ()
    No symbol table info available.
    #15 0x00007ffc38dc5fba in ?? ()
    No symbol table info available.
    #16 0x0000000000000000 in ?? ()
    No symbol table info available.

    6. 小结

    对比以上几个内存你检查手段:MALLOC_CHECK_最简单,其次是-lmcheck,最后是mtrace()/muntrace()、mcheck()、mprobe()。

    但是这几种技术检查的全面性都不够,没有一种能够全面检查内存泄漏、内存踩踏、重复释放的。

    要想全面的检查还是需要Valgrind这种技术,参考《valgrind使用方法》。

    参考文档:《mtrace-内存使用追踪(内存)》、《mcheck 函数使用(glibc-3-内存)

  • 相关阅读:
    前端分页功能的实现以及原理
    Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
    Jquery实现的几款漂亮的时间轴
    jQuery点击弹出层,弹出模态框,点击模态框消失
    如何用CSS快速布局(一)—— 布局元素详细
    验证控件jQuery Validation Engine调用外部函数验证
    Javascript实现页面跳转的几种方式
    最详细win7下手动搭建PHP环境:apache2.4.23+php7.0.11
    spark调优——JVM调优
    spark调优——Shuffle调优
  • 原文地址:https://www.cnblogs.com/arnoldlu/p/10827884.html
Copyright © 2011-2022 走看看