在C語言編程裏,最常見的內存問題就是使用了malloc分配的內存,忘記釋放(free)造成的內存泄漏。今天介紹一個內存檢測工具Valgrind。

在Linux系統上,如Unbuntu安裝Valgrind:

apt-get install valgrind

我先寫一個內存泄漏的代碼,然後演示如何使用valgrind來找到泄漏點。

使用Valgrind檢測內存問題(C語言)_數組

編譯帶調試信息的可執行文件

# gcc -g tt.c -o tt

-g 告訴 GCC 在編譯 / 鏈接過程中,將調試信息(Debug Information) 嵌入到生成的目標文件(.o)或可執行文件中。這些調試信息包括:

  • 源代碼行號與機器指令的映射關係;
  • 變量名、函數名、類型信息(不再被剝離);
  • 源代碼文件路徑、函數參數 / 局部變量的存儲位置等。
  • 沒有 -g 時,GCC 生成的可執行文件會默認剝離調試信息,僅保留運行所需的機器碼,此時用 gdb 調試只能看到彙編指令,無法關聯源代碼,也無法查看 / 修改變量。

使用valgrind檢測內存問題

valgrind --tool=memcheck ./tt

memcheck 是默認工具,可省略 --tool=memcheck。

valgrind ./tt

使用Valgrind檢測內存問題(C語言)_數組_02


從上圖,我們知道,程序一共申請了2塊內存,釋放了一次,在程序退出時,還有一塊1字節內存沒有釋放。

memcheck 本質是一個 “內存檢測模擬器”,它會讓程序在 Valgrind 的虛擬 CPU 中運行,全程監控每一次內存操作(分配 / 釋放 / 訪問),能檢測出以下高頻問題:

  • 內存泄漏 (Memory Leak) ,如malloc/new 分配後未 free/delete
  • 數組 / 指針越界訪問 int a[5]; a[5] = 10;(訪問超出數組範圍)
  • 使用未初始化的內存 int x; printf(“%d”, x);
  • 重複釋放內存 free§; free§;
  • 釋放後仍訪問內存 (野指針) free§; printf(“%d”, *p);
  • 內存分配 / 釋放不匹配 new[] 分配卻用 delete 釋放
  • 棧內存溢出,局部數組過大 / 遞歸過深導致棧越界

使用–leak-check=full查找泄漏點

使用Valgrind檢測內存問題(C語言)_數組_03

從上面的信息,可知tt.c的第8行出了問題。