關鍵詞: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 ***\n") 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.\n"); else if(mstatus == MCHECK_HEAD) fprintf(stderr, "Memory before the block was clobbered.\n"); else if(mstatus == MCHECK_TAIL) fprintf(stderr, "Memory after the block was clobbered.\n"); else fprintf(stderr, "Block is fine.\n"); } void main(void) { char *s = NULL; if(mcheck(abortfun) != 0) { fprintf(stderr, "mcheck:%s\n", 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.\n"); else if(mstatus == MCHECK_HEAD) fprintf(stderr, "Memory before the block was clobbered.\n"); else if(mstatus == MCHECK_TAIL) fprintf(stderr, "Memory after the block was clobbered.\n"); else fprintf(stderr, "Block is fine.\n"); } void main(void) { char *s = NULL; if(mcheck(abortfun) != 0) { fprintf(stderr, "mcheck:%s\n", 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 ***\n") 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-內存)》