linux下內存檢測工具的使用和對比


linux背后隱藏着各種豐富的工具,學會這些工具,讓這些工具更好地服務於我們的項目開發,不僅可以提高工作的效率,而且可以增強個人技術力。

參考:http://blog.chinaunix.net/uid-16135252-id-2752984.html

內存檢測工具有以下的幾種:

mtrace、memwatch、splint、valgrind

對比:

   mtrace: 無需安裝,使用時包含頭文件mcheck.h,程序中調用mtrace和muntrace方法即可

   memwatch: 在需要檢測的.c文件里面包含memwatch.h文件,編譯的時候加上幾個參數即可

   splint:需要下載源碼並安裝程序,通過標志和注釋來獲取想要的錯誤信息

   valgrind:提供不同的工具來實現不同功能的檢測,需要編譯源碼

各工具的使用

一、mtrace工具

mtrace是三款工具之中是最簡單易用的,mtrace是一個C函數,在<mcheck.h>里聲明及定義,函數原型為:

    void mtrace(void);

其實mtrace是類似malloc_hook的malloc handler,只不過mtrace的handler function已由系統為你寫好,但既然如此,系統又怎么知道你想將malloc/free的記錄寫在哪里呢?為此,調用mtrace()前要先設置MALLOC_TRACE環境變量:

    #include <stdlib.h>     ....    
   setenv("MALLOC_TRACE", "output_file_name", 1);     ...
  還可以通過export MALLOC_TRACE = output_file_name進行環境變量的設置

「output_file_name」就是儲存檢測結果的文件的名稱。

但是檢測結果的格式是一般人無法理解的,而只要有安裝mtrace的話,就會有一名為mtrace的Perl script,在shell輸入以下指令:

    mtrace [binary] output_file_name

就會將output_file_name的內容轉化成能被理解的語句,例如「No memory leaks」,「0x12345678 Free 10 was never alloc」諸如此類。

例如以下有一函數:(暫且放下single entry single exit的原則)

   #include <stdio.h>    
   #include <stdlib.h>    
   #include <errno.h>    
   #include <mcheck.h>    
   int main()
   {        
        char *hello;            
        setenv("MALLOC_TRACE", "output", 1);        
        mtrace();        
       if ((hello = (char *) malloc(sizeof(char))) == NULL)
      {            
           perror("Cannot allocate memory.");          
          return -1;       
      }
        return 0;    
    }

執行后,再用mtrace 將結果輸出:

    …………………………………………
  ………………………………………………
    Memory not freed:     -----------------        Address     Size     Caller     0x08049a90      0x1  at 0x80483fe

最后一行標明有一個大小為1 byte的內存尚未釋放,應該就是指hello

    若我們把該段內存釋放:

    #include <stdio.h>    
    #include <stdlib.h>    
   #include <errno.h>    
   #include <mcheck.h>    
  int main()
  {        
        char *hello;            
        setenv("MALLOC_TRACE", "output", 1);        
        mtrace();        
        if ((hello = (char *) malloc(sizeof(char))) == NULL)
       {            
            perror("Cannot allocate memory.");            
            return -1;        
       }
 
            free(hello);        
            return 0;    
  }

結果如下:

         ……………………
         ……………………
         No memory leaks.

mtrace的原理是記錄每一對malloc-free的執行,若每一個malloc都有相應的free,則代表沒有內存泄露,對於任何非malloc/free情況下所發生的內存泄露問題,mtrace並不能找出來。

二、memwatch工具

在三種檢測工具當中,設置最簡單的算是memwatch,和dmalloc一樣,它能檢測未釋放的內存、同一段內存被釋放多次、位址存取錯誤及不當使用未分配之內存區域,溢出和下溢等錯誤。請在http://www.linkdata.se/sourcecode.html下載最新版本的Memwatch。  

步驟:

  1. 確保被測工程中有memwatch.c和memwatch.h文件,
  1. 源碼中每個.c文件中都include頭文件memwatch.h
  1. 編譯代碼,gcc后添加-DMEMWATCH -DMW_STDIO或者-DMEMWATCH_STDIO,還有memwatch.c文件,例如:

                 gcc -DMEMWATCH -DMW_STDIO test.c memwatch.c -o test

  1. 運行生成的可執行文件,程序運行結束后,生成的log文件名為memwatch.log,而且在程序執行期間,所有錯誤提示都會顯示在stdout上

                  如果未生成上述文件,則會寫入memwatNN.log文件,NN01~99,如果還未成功,則放棄寫log文件。

    :memwatch會使系統速度減慢

 

    三、splint的使用

         1.splint是靜態代碼檢測工具,可以檢查包括:

                1)Null Dereferences:針對空指針

                2)Undefined Values:未初始化數據

                3)Types:轉化類型不一致

                4)Memory Management:內存管理檢測,如內存泄露

                5)sharing:共享存儲空間安全性檢測

                6)Function Interfaces:函數接口檢測(參數傳遞等)

                7)Control Flow:函數執行分支檢測

                8)Buffer Sizes:緩沖區邊界檢查

                9)Completeness:完整性檢查,包括未使用變量、函數等

                10)Macros(宏隱患檢測等)

 

          2.源碼包安裝:

             #tar zxvf splint-3.1.2.src.tgz

             #cd splint-3.1.2

             #mkdir /usr/local/splint

             #./configure --prefix=/usr/local/splint

             #make

              #make install

              #vi ~/.bashrc    (或者 sudo gedit ~/.bashrc) ~目錄是/root

              向其中添加以下內容:

                  export LARCH_PATH=/usr/local/splint/share/splint/lib

                  export LCLIMPORTDIR=/usr/local/splint/share/splint/import

 

              #source ~/.bashrc

              #export PATH=/usr/local/splint/bin/splint:$PATH

           到此,splint源碼安裝完成。

    3.splint提供了三種方式進行檢查的控制,分別是flags標志、 .splintrc配置文件和格式化注釋。

      flags: splint支持幾百個標志用來控制檢查和消息報告,使用時標志前加‘+’或‘-’,‘+’標志開啟這個標志,‘-’表示關閉此標志。下面例子展示了flags標志的用法:

      splint -showcol a.c //在檢測a.c時,告警消息中列數不被打印

      splint -varuse a.c //在檢測a.c時,告警消息中未使用變量告警不被打印

      .splintrc配置文件: .splintrc文件中對一些flags做了默認的設定,命令行中指定的flags會覆蓋.splintrc文件中的標志。

    格式化注釋:格式化注釋提供一個類型、變量或函數的額外的信息,可以控制標志設置,增加檢查效果。所有格式化注釋都以/*@開始,@*/結束,比如在函數參數前加/*@null@*/,表示該參數可能是NULL,做檢測時,splint會加強對該參數的值的檢測。

 

 

四. valgrind使用:

 

步驟:

1tar -xf valgrind-3.9.0.tar.bz2

2./configure

3make

4make install(如果失敗,改用root權限)

5valgrind ls -l(檢查是否正常工作,如果出錯,按照提示安裝相應文件)

 

下面的工具是valgrind安裝時的標准配置:

Memcheck:用於檢測內存錯誤。它幫助cc++的程序更正確。

Cachegrind:用於分析cache和分支預測。它幫助程序執行得更快。

Callgrind:用於函數調用的分析。

Helgrind:用於分析多線程。

DRD:也用於分析多線程。與Helgrind類似,但是用不同的分析技術,所以可以檢測不同的問題。

Massif:用於分析堆。它幫助程序精簡內存的使用。

SGcheck:檢測棧和全局數組溢出的實驗性工具,它和Memcheck互補使用。

 

--leak-check=yes打開內存泄露檢測細節

--tool=helgrind使用Helgrind工具檢測線程錯誤

 

假設hello是可執行程序:可能的使用方法如下

valgrind --leak-check=yes ./hello

或者valgrind ./hello

終端上顯示檢測信息。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM