內存泄漏檢測

我在Linux編程中通常使用三種方法檢測內存泄漏。

第一種方法是閱讀程序源代碼,打印和查看日誌,觀察分析程序的執行。

第二種方法使用valgrind:
    假設名爲mytest的程序可能有內存泄漏的情況。
    那麼執行命令:
        valgrind -v --tool=memcheck --leak-check=full ./mytest
    valgrind會打印出很多信息,比較重要的摘錄如下:

        ==3127== malloc/free: in use at exit: 256 bytes in 1 blocks.
        ==3127== malloc/free: 4 allocs, 3 frees, 480 bytes allocated.
        ==3127==
        ==3127== searching for pointers to 1 not-freed blocks.

    上述信息表明存在內存泄漏。修改程序後再次執行:
        valgrind -v --tool=memcheck --leak-check=full ./mytest
    valgrind打印的信息摘錄如下:

        ==3155== malloc/free: in use at exit: 0 bytes in 0 blocks.
        ==3155== malloc/free: 4 allocs, 4 frees, 480 bytes allocated.
        ==3155==
        ==3155== All heap blocks were freed -- no leaks are possible.

    上述信息表明已經沒有內存泄漏了。

第三種方法使用mtrace:
    首先有如下用於實驗的程序代碼,main.cpp:
        #include <iostream>
        #include <cstdlib>
        #include <cstring>

        #include <mcheck.h>

        using namespace std;

        int main()
        {
            mtrace();

            char *p = (char *)malloc(128);
            free(p);
            p = (char *)calloc(256, 1);
            free(p);
            p = (char *)malloc(64);
            //free(p);
            p = new char [32];
            delete [] p;

            muntrace();

            return 0;
        }

    編譯:
        g++ -g -W -Wall -Wextra -o mytest main.cpp

    函數mtrace給內存分配函數安裝handler,muntrace函數禁止這些handler。
    這兩個函數聲明在mcheck.h文件中。mtrace會將環境變量MALLOC_TRACE指定
    的文件截短爲0,以便向該文件寫入相關的內存信息。因此使用如下命令
    執行程序:
        env MALLOC_TRACE=./mcheck.txt ./mytest

    調用muntrace函數之後,程序會將內存的動態分配信息寫入
    環境變量MALLOC_TRACE指定的文件,這個例子生成的是
    名爲mcheck.txt的文件。之後可以通過查看該文件的內容
    來檢測是否存在內存泄漏:
    (不同的計算機生成的文件內容可能是不同的)
        = Start
        @ ./mytest:[0x80486ae] + 0x8ba0378 0x80
        @ ./mytest:[0x80486be] - 0x8ba0378
        @ ./mytest:[0x80486d2] + 0x8ba0378 0x100
        @ ./mytest:[0x80486e2] - 0x8ba0378
        @ ./mytest:[0x80486ee] + 0x8ba0378 0x40
        @ /usr/lib/libstdc++.so.6:(_Znwj+0x27)[0x6cceb27] + 0x8ba03c0 0x20
        @ /usr/lib/libstdc++.so.6:(_ZdlPv+0x21)[0x6ccc681] - 0x8ba03c0
        = End

    從文件中可以看到內存分配的地址和空間大小,以及內存的分配和釋放的次數。
    加號代表分配,減號代表釋放。有四個加號,而減號只有三個,說明有內存泄漏發生。
    修改上面源代碼的第24行,再次編譯執行,mcheck.txt的內容變爲:
        = Start
        @ ./mytest:[0x80486ae] + 0x9765378 0x80
        @ ./mytest:[0x80486be] - 0x9765378
        @ ./mytest:[0x80486d2] + 0x9765378 0x100
        @ ./mytest:[0x80486e2] - 0x9765378
        @ ./mytest:[0x80486ee] + 0x9765378 0x40
        @ ./mytest:[0x80486fe] - 0x9765378
        @ /usr/lib/libstdc++.so.6:(_Znwj+0x27)[0x6cceb27] + 0x97653c0 0x20
        @ /usr/lib/libstdc++.so.6:(_ZdlPv+0x21)[0x6ccc681] - 0x97653c0
        = End

    沒有內存泄漏了。


參考文獻:
    mtrace(3), malloc_hook(3)

發佈了43 篇原創文章 · 獲贊 12 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章