記憶體洩露檢查函式 mtrace

2021-07-10 08:10:09 字數 4497 閱讀 1177

c語言中乙個malloc呼叫與乙個free呼叫對應出現。

當專案足夠大的時候,我們就很容易忘記free記憶體,或者重複free記憶體。

在一般linux發行版中,有一些自帶的記憶體檢查工具可以幫助我們去檢查對手動分配的記憶體的free情況,其中的乙個工具就是mtrace。
使用mtrace之前需要在c原始碼中使用gnu c函式mtrace追蹤記錄記憶體的分配釋放情況。

mtrace()包含在標頭檔案mcheck.h中,與之配對的函式是muntrace(),函式原型分別為:

#include

void mtrace(void);

void muntrace(void);

呼叫mtrace追蹤前需要設定環境變數malloc_trace,可以使用export命令也可以使用setenv函式:

export: export malloc_trace=""

或者:setenv: assert(!setevn("malloc_trace", "", 1));

其中是log檔名,用來儲存mtrace生成的追蹤記錄。

事例中將使用export命令方法。

使用mtrace追蹤記憶體申請與釋放的流程:(表示可選項,可有可無)

1:export malloc_trace=""

2:在c原始碼中加入mtrace();

3:gcc -g [-o destinationbin]

4:執行程式

5:mtrace [destinationbin]

事例:1:設定環境變數

export malloc_trace=mcheck.log

export可以指定log的路徑,也可以不指定,則生成的log檔案在儲存在程式執行的目錄下。

2:原始碼

//filename: mcheck.c

#include

#include

int main()                 

3:編譯

gcc -g -o mcheck mcheck.c

4:執行程式

5:mtrace mcheck mcheck.log

執行完程式後,會在程式執行的當前目錄下生成乙個名為mcheck.log的檔案,檔案內容:

= start

@ ./mcheck:[0x804844a] + 0x9780378 0xa

@ ./mcheck:[0x8048456] + 0x9780388 0xf

@ ./mcheck:[0x804845e] - 0x9780388

裡面儲存了申請記憶體的超始位址和記憶體大小,比如0x9780378是m1指向的起始位址,0xa(10)記憶體大小,而前面的"+"號表示申請記憶體,"-"表示釋放記憶體。

從上面可以看出程式釋放了起始位址為0x9780388的空間,但0x9780378開始的記憶體空間沒有進行釋放的記錄。從0xa和0xf可以看出0x9780378是m1所指向的空間而0x9780388是m2所指向的空間,從**可看出程式對m2的空間進行的釋放而沒有對m1的記憶體空間進行釋放。因此檢查結果符合實際情況。

上面的例程很短,可以直接從log檔案中直接看出問題所在。但是如果程式足夠大,我們就很難去查詢問題,因此我們可以使用工具mtrace去分析log檔案。

執行第5步時會在終端下輸出:

memory not freed:

-----------------

address     size     caller

0x09780378      0xa  at /home/fyl/testpro/mcheck.c:9

從輸出的第1行就可以發現了例程沒有free記憶體,而沒有釋放的記憶體空間起始位址是:0x09780378,記憶體空間大小:0xa,呼叫的地方:mcheck.c的第9行。

於是我們就可以根據實際需求去釋放內容,從而避免在程式執行時出現記憶體洩漏。

如果我們執行第5步時沒有加上相應的程式名,而是這樣執行:mtrace mtrace.log,就會輸出以下資訊:

memory not freed:

-----------------

address     size     caller

0x09780378      0xa  at 0x804844a

比較一下,就會發現caller列變成了乙個位址,而不是原始檔所在的位置。

為了能你上面的caller那樣可以顯示出申請記憶體的操作在原始檔中的位置,在編譯程式時需要新增gcc選項-g。

前面說到與mtrace呼叫相匹配的呼叫是muntrace,至於使用時候呼叫起muntrace看自身情況需求。但是一般情況下可以在原始檔最後新增,也可以不顯式呼叫它,而是由程式自行結束時關閉mtrace。

因為申請過的記憶體,有可能不是馬上釋放的,如果呼叫了muntrace就有可能檢查不正確。

將源**修改一下:

//filename: mcheck.c

#include

#include

int main()                 

如果不新增mtrace()呼叫,則上面例程會報出:

*** glibc detected *** ./mcheck: double free or corruption (fasttop): 0x099de018 ***

*****== backtrace: *****====

/lib/libc.so.6[0xc85c81]

/lib/libc.so.6[0xc885c2]

./mcheck[0x8048445]

/lib/libc.so.6(__libc_start_main+0xe6)[0xc2bd36]

./mcheck[0x8048361]

*****== memory map: *****===

0027a000-0027b000 r-xp 00000000 00:00 0          [vdso]

00b54000-00b71000 r-xp 00000000 fd:00 2760424    /lib/libgcc_s-4.4.7-20120601.so.1

00b71000-00b72000 rw-p 0001d000 fd:00 2760424    /lib/libgcc_s-4.4.7-20120601.so.1

00bf3000-00c11000 r-xp 00000000 fd:00 2760408    /lib/ld-2.12.so

00c11000-00c12000 r--p 0001d000 fd:00 2760408    /lib/ld-2.12.so

00c12000-00c13000 rw-p 0001e000 fd:00 2760408    /lib/ld-2.12.so

00c15000-00da5000 r-xp 00000000 fd:00 2760409    /lib/libc-2.12.so

00da5000-00da6000 ---p 00190000 fd:00 2760409    /lib/libc-2.12.so

00da6000-00da8000 r--p 00190000 fd:00 2760409    /lib/libc-2.12.so

00da8000-00da9000 rw-p 00192000 fd:00 2760409    /lib/libc-2.12.so

00da9000-00dac000 rw-p 00000000 00:00 0 

08048000-08049000 r-xp 00000000 fd:02 524499     /home/fyl/testpro/mcheck

08049000-0804a000 rw-p 00000000 fd:02 524499     /home/fyl/testpro/mcheck

099de000-099ff000 rw-p 00000000 00:00 0          [heap]

b7600000-b7621000 rw-p 00000000 00:00 0 

b7621000-b7700000 ---p 00000000 00:00 0 

b7731000-b7732000 rw-p 00000000 00:00 0 

b7743000-b7745000 rw-p 00000000 00:00 0 

bfb78000-bfb8d000 rw-p 00000000 00:00 0          [stack]

已放棄 (core dumped)

如果新增了mtrace(),程式只報

*** glibc detected *** ./mcheck: double free or corruption (fasttop): 0x09dbc388 ***

之後就卡住了,至少在機子上測試時是這樣。

因此在釋放記憶體後需要將指標置null,因為free(null)是沒問題的。

但是如果人人都注意到些問題,那麼也就既不會忘記free,也不會多次free了,更不需要測試了。

因此,mtrace沒辦法檢查下去,就需要使用其他方法了。

關於記憶體洩露追蹤函式mtrace

關於 mtrace調查 記憶體洩露的過程,mtrace是glibc的乙個函式,他的機制實際上是把記憶體洩露資訊列印到環境變數到malloc trace設 置的 檔案裡,然後使用mtrace命令來檢視log資訊,因為mtrace呼叫會增加 系統開銷,所以一般放在debug巨集定義中 比如說下面的函式 ...

mtrace檢查記憶體洩漏

記憶體洩漏檢查方法 for linux 如果你更想讀原始文件,請參考glibc info的 allocation debugging 一章 執行info libc glibc提供了乙個檢查記憶體洩漏的方法,前提是你的程式使用glibc的標準函式分配記憶體 如malloc,alloc.1.在需要記憶體...

mtrace 檢查記憶體洩漏

mtrace 可以用來檢查記憶體洩漏。它利用 malloc hook機制,記錄每乙個記憶體分配的呼叫,在利用gcc的 builtin return address 獲得函式的呼叫位址,生成log檔案。最後通過 程式中的除錯資訊和日誌檔案找出發生記憶體洩漏的函式。記住程式編譯時要帶上除錯資訊,不然只有...