C 語言缺乏垃圾回收機制,開發者必須手動管理動態記憶體的分配與釋放。一旦發生「有借無還」的情況——即呼叫 malloc、realloc 分配記憶體後忘記呼叫 free 釋放,程式就會產生記憶體洩漏。隨著程式碼規模增長,要在茫茫程式碼海中定位洩漏點無異大海撈針。幸運的是,GNU C Library (glibc) 內建了 mtrace 與 muntrace 兩個函式,配合 MALLOC_TRACE 環境變數,能輕鬆記錄並分析動態記憶體操作。
執行程式前,必須指定一個可寫入的一般檔案路徑給 MALLOC_TRACE:
export MALLOC_TRACE=/your/path/to/mtrace.log
在 main 函式開頭呼叫 mtrace() 安裝特殊處理器,攔截 malloc、realloc、free 的呼叫並記錄到指定檔案;在 return 前呼叫 muntrace() 卸載處理器,結束追蹤。
#include <mcheck.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
#ifdef DEBUG
mtrace(); // 僅在除錯建置時啟用
#endif
int *a = malloc(sizeof(int));
// 故意不呼叫 free(a) 以示範洩漏
#ifdef DEBUG
muntrace();
#endif
return 0;
}
注意: 不建議在生產程式碼中省略 muntrace(),因為 C 函式庫本身也會使用動態記憶體,過早卸載可能干擾庫內部追蹤。
使用 -DDEBUG 宏編譯並執行:
gcc -DDEBUG -o leak_demo leak_demo.c ./leak_demo
原始日誌為機器可讀格式,需透過 mtrace 指令轉換為人類可讀報告:
mtrace leak_demo mtrace.log
Memory not freed:
-------------------
Address Size Caller
0x092a6378 0x4 at /root/tmp.c:9
輸出明確指出:第 9 行的 malloc 分配了 4 位元組記憶體,但對應的 free 從未被呼叫。這讓定位洩漏點變得極其簡單。
#ifdef DEBUG 包裹追蹤呼叫,發布版本自動移除額外開銷。mtrace 非執行緒安全,多執行緒程式需自行加鎖或改用 valgrind 等工具。mtrace 分析整合至 CI/CD 流程,自動偵測記憶體洩漏回歸。mtrace/muntrace 是 Linux C 開發者針對動態記憶體洩漏的輕量級利器。只需三步驟——設定環境變數、植入兩行程式碼、跑一次分析指令,即可快速定位「有借無還」的記憶體分配點,大幅降低除錯成本。掌握此技巧,讓你的 C 程式更穩健、更專業。