valgrind安裝及使用方法詳解

Valgrind manual:

http://valgrind.org/docs/manual/manual.htmlphp

 

valgrind介紹:

l   Valgrind查找內存泄露利器html

Valgrind是一個GPL的軟件,用於Linux(For x86, amd64 and ppc32)程序的內存調試和代碼剖析。你能夠在它的環境中運行你的程序來監視內存的使用狀況,好比C 語言中的malloc和free或者 C++中的new和 delete。使用Valgrind的工具包,你能夠自動的檢測許多內存管理和線程的bug,避免花費太多的時間在bug尋找上,使得你的程序更加穩固。前端

l  Valgrind的主要功能
Valgrind工具包包含多個工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。下面分別介紹個工具的做用:linux

l  Memcheck 工具主要檢查下面的程序錯誤:算法

使用未初始化的內存 (Use of uninitialised memory)
使用已經釋放了的內存 (Reading/writing memory after it has been free’d)
使用超過 malloc分配的內存空間(Reading/writing off the end of malloc’d blocks)
對堆棧的非法訪問 (Reading/writing inappropriate areas on the stack)
申請的空間是否有釋放 (Memory leaks – where pointers to malloc’d blocks are lost forever)
malloc/free/new/delete申請和釋放內存的匹配(Mismatched use of malloc/new/new [] vs free/delete/delete [])
src和dst的重疊(Overlapping src and dst pointers in memcpy() and related functions)vim

l  Callgrind數組

Callgrind收集程序運行時的一些數據,函數調用關係等信息,還能夠有選擇地進行cache模擬。在運行結束時,它會把分析數據寫入一個文件。callgrind_annotate能夠把這個文件的內容轉化成可讀的形式。緩存

l  Cachegrind網絡

它模擬 CPU中的一級緩存I1,D1和L2二級緩存,可以精確地指出程序中 cache的丟失和命中。若是須要,它還可以爲咱們提供cache丟失次數,內存引用次數,以及每行代碼,每一個函數,每一個模塊,整個程序產生的指令數。這對優化程序有很大的幫助。多線程

l  Helgrind

它主要用來檢查多線程程序中出現的競爭問題。Helgrind尋找內存中被多個線程訪問,而又沒有一向加鎖的區域,這些區域每每是線程之間失去同步的地方,並且會致使難以發掘的錯誤。Helgrind實現了名爲」 Eraser」 的競爭檢測算法,並作了進一步改進,減小了報告錯誤的次數。

l  Massif

堆棧分析器,它能測量程序在堆棧中使用了多少內存,告訴咱們堆塊,堆管理塊和棧的大小。

Massif能幫助咱們減小內存的使用,在帶有虛擬內存的現代系統中,它還可以加速咱們程序的運行,減小程序停留在交換區中的概率。

 

 

valgrind下載:

http://valgrind.org/downloads/valgrind-3.12.0.tar.bz2

 

valgrind安裝:

1. tar -jxvf valgrind-3.12.0.tar.bz2

2. cd valgrind-3.12.0

3. ./configure

config.status: creating config.h

config.status: executing depfiles commands

 

         Maximum build arch: amd64

         Primary build arch: amd64

       Secondary build arch:

                   Build OS: linux

       Primary build target: AMD64_LINUX

     Secondary build target:

           Platform variant: vanilla

      Primary -DVGPV string: -DVGPV_amd64_linux_vanilla=1

         Default supp files: exp-sgcheck.supp xfree-3.supp xfree-4.supp glibc-2.X-drd.supp glibc-2.34567-NPTL-helgrind.supp glibc-2.X.supp

4. make

5. make install

 

輸入valgrind–h顯示valgrind的參數及提示,說明安裝成功

 

 

Valgrind的使用方法:

 

1.檢查內存錯誤:
例如咱們原來有一個程序sec_infod,這是一個用gcc –g參數編譯的程序,運行它須要:
#./a.out
若是咱們想用valgrind的內存檢測工具,咱們就要用以下方法調用:
#valgrind --leak-check=full --show-reachable=yes --trace-children= yes   ./a.out (2>logfile加上會好些,程序在執行期間stderr會有一些輸出。提示比較多)

其中--leak-check=full指的是徹底檢查內存泄漏,--show-reachable=yes是顯示內存泄漏的地點,--trace-children=yes是跟入子進程。

若是您的程序是會正常退出的程序,那麼當程序退出的時候valgrind天然會輸出內存泄漏的信息。若是您的程序是個守護進程,那麼也沒關係,咱們 只要在別的終端下殺死memcheck進程(由於valgrind默認使用memcheck工具,就是默認參數—tools=memcheck):
#killall memcheck
這樣咱們的程序(./a.out)就被kill了

2,檢查代碼覆蓋和性能瓶頸:
咱們調用valgrind的工具執行程序:
#valgrind --tool=callgrind ./sec_infod

會在當前路徑下生成callgrind.out.pid(當前生產的是callgrind.out.19689),若是咱們想結束程序,能夠:
#killall callgrind
而後咱們看一下結果:
#callgrind_annotate --auto=yes callgrind.out.19689   >log
#vim log

 

參數解釋:

名字:
       valgrind是一個調試和剖析的程序工具集。

概要用法:
       valgrind [[valgrind] [options]] [your-program] [[your-program-options]]

概述:
       Valgrind是一個Linux下靈活的調試和剖析可執行工具。它由在軟件層提供綜合的
       CPU內核,和一系列調試、剖析的工具組成。架構是模塊化的,因此能夠在不破壞現
       有的結構的基礎上很容易的建立出新的工具來。
       這本手冊包括了基本的用法和選項。更多幫助理解的信息,請查看您系統的HTML
       文檔:
         /usr/share/doc/valgrind/html/index.html
       或者在線文檔:
         http://www.valgrind.org/docs/manual/index.html.

用法:
       通常像下面這樣調用Valgrind:
           valgrind program args

      這樣將在Valgrind使用Memcheck運行程序program(帶有參數args)。內存檢查
       執行一系列的內存檢查功能,包括檢測訪問未初始化的內存,已經分配內存的錯誤
       使用(兩次釋放,釋放後再訪問,等等)並檢查內存泄漏。

      可用--tool指定使用其它工具:
           valgrind --tool=toolname program args

      可以使用的工具以下:
       o cachegrind是一個緩衝模擬器。它能夠用來標出你的程序每一行執行的指令
          數和致使的緩衝不命中數。

       o callgrind在cachegrind基礎上添加調用追蹤。它能夠用來獲得調用的次數
          以及每次函數調用的開銷。做爲對cachegrind的補充,callgrind能夠分別
          標註各個線程,以及程序反彙編輸出的每條指令的執行次數以及緩存未命中
          數。

       o helgrind可以發現程序中潛在的條件競爭。

       o lackey是一個示例程序,以其爲模版能夠建立你本身的工具。在程序結束後,
       它打印出一些基本的關於程序執行統計數據。

       o massif是一個堆剖析器,它測量你的程序使用了多少堆內存。

       o memcheck是一個細粒度的的內存檢查器。

       o none沒有任何功能。它它通常用於Valgrind的調試和基準測試。

基本選項:
       這些選項對全部工具都有效。

       -h --help
              顯示全部選項的幫助,包括內核和選定的工具二者。

       --help-debug
              和--help相同,而且還能顯示一般只有Valgrind的開發人員使用的調試
              選項。

       --version
              顯示Valgrind內核的版本號。工具能夠有他們自已的版本號。這是一種
              保證工具只在它們能夠運行的內核上工做的一種設置。這樣能夠減小在
              工具和內核之間版本兼容性致使奇怪問題的機率。

       -q --quiet
              安靜的運行,只打印錯誤信息。在進行迴歸測試或者有其它的自動化測
              試機制時會很是有用。

       -v --verbose
              顯示詳細信息。在各個方面顯示你的程序的額外信息,例如:共享對象
              加載,使用的重置,執行引擎和工具的進程,異常行爲的警告信息。重
              復這個標記能夠增長詳細的級別。

       -d    調試Valgrind自身發出的信息。一般只有Valgrind開發人員對此感興趣。
              重複這個標記能夠產生更詳細的輸出。若是你但願發送一個bug報告,通
              過-v -v -d -d生成的輸出會使你的報告更加有效。

       --tool= [default: memcheck]
              運行toolname指定的Valgrind,例如,Memcheck, Addrcheck, Cachegrind,
              等等。

       --trace-children= [default: no]
              當這個選項打開時,Valgrind會跟蹤到子進程中。這常常會致使困惑,而
              且一般不是你所指望的,因此默認這個選項是關閉的。

       --track-fds= [default: no]
              當這個選項打開時,Valgrind會在退出時打印一個打開文件描述符的列表。
              每一個文件描述符都會打印出一個文件是在哪裏打開的棧回溯,和任何與此
              文件描述符相關的詳細信息好比文件名或socket信息。


       --time-stamp= [default: no]
              當這個選項打開時,每條信息以前都有一個從程序開始消逝的時間,用天,
              小時,分鐘,秒和毫秒錶示。

       --log-fd= [default: 2, stderr]
              指定Valgrind把它全部的消息都輸出到一個指定的文件描述符中去。默認值
              2, 是標準錯誤輸出(stderr)。注意這可能會干擾到客戶端自身對stderr
              的使用, Valgrind的輸出與客戶程序的輸出將穿插在一塊兒輸出到stderr。

       --log-file=
              指定Valgrind把它全部的信息輸出到指定的文件中。實際上,被建立文件的
              文件名是由filename、'.'和進程號鏈接起來的(即.),
              從而每一個進程建立不一樣的文件。

       --log-file-exactly=
              相似於--log-file,可是後綴".pid"不會被添加。若是設置了這個選項,
              使用Valgrind跟蹤多個進程,可能會獲得一個亂七八糟的文件。             

       --log-file-qualifier=
              當和--log-file一塊兒使用時,日誌文件名將經過環境變量$VAR來篩選。這
              對於MPI程序是有益的。更多的細節,查看手冊2.3節 "註解"。

       --log-socket=
              指定Valgrind輸出全部的消息到指定的IP,指定的端口。當使用1500端口
              時,端口有可能被忽略。若是不能創建一個到指定端口的鏈接,Valgrind
              將輸出寫到標準錯誤(stderr)。這個選項常常和一個Valgrind監聽程序一
              起使用。更多的細節,查看手冊2.3節 "註解"。


錯誤相關選項:
       這些選項適用於全部產生錯誤的工具,好比Memcheck, 可是Cachegrind不行。

       --xml= [default: no]
              當這個選項打開時,輸出將是XML格式。這是爲了使用Valgrind的輸出作爲
              輸入的工具,例如GUI前端更加容易些。目前這個選項只在Memcheck時生效。

       --xml-user-comment=
              在XML開頭 附加用戶註釋,僅在指定了--xml=yes時生效,不然忽略。

       --demangle= [default: yes]
              打開/關閉C++的名字自動解碼。默認打開。當打開時,Valgrind將嘗試着把
              編碼過的C++名字自動轉回初始狀態。這個解碼器能夠處理g++版本爲2.X,
              3.X或4.X生成的符號。

             一個關於名字編碼解碼重要的事實是,禁止文件中的解碼函數名仍然使用
              他們未解碼的形式。Valgrind在搜尋可用的禁止條目時不對函數名解碼,
              由於這將使禁止文件內容依賴於Valgrind的名字解碼機制狀態, 會使速度
              變慢,且無心義。

       --num-callers= [default: 12]
              默認狀況下,Valgrind顯示12層函數調用的函數名有助於肯定程序的位置。
              能夠經過這個選項來改變這個數字。這樣有助在嵌套調用的層次很深時肯定
              程序的位置。注意錯誤信息一般只回溯到最頂上的4個函數。(當前函數,和
              它的3個調用者的位置)。因此這並不影響報告的錯誤總數。

             這個值的最大值是50。注意高的設置會使Valgrind運行得慢,而且使用更多
              的內存,可是在嵌套調用層次比較高的程序中很是實用。

       --error-limit= [default: yes]
              當這個選項打開時,在總量達到10,000,000,或者1,000個不一樣的錯誤,
              Valgrind中止報告錯誤。這是爲了不錯誤跟蹤機制在錯誤不少的程序
              下變成一個巨大的性能負擔。

       --error-exitcode= [default: 0]
              指定若是Valgrind在運行過程當中報告任何錯誤時的退出返回值,有兩種情
              況;當設置爲默認值(零)時,Valgrind返回的值將是它模擬運行的程序的
              返回值。當設置爲非零值時,若是Valgrind發現任何錯誤時則返回這個值。
              在Valgrind作爲一個測試工具套件的部分使用時這將很是有用,由於使測
              試工具套件只檢查Valgrind返回值就能夠知道哪些測試用例Valgrind報告
              了錯誤。

       --show-below-main= [default: no]
              默認地,錯誤時的棧回溯不顯示main()之下的任何函數(或者相似的函數像
              glibc的__libc_start_main(),若是main()沒有出如今棧回溯中);這些大
              部分都是使人厭倦的C庫函數。若是打開這個選項,在main()之下的函數也
              將會顯示。

       --suppressions= [default: $PREFIX/lib/valgrind/default.supp]
              指定一個額外的文件讀取不須要理會的錯誤;你能夠根據須要使用任意多
              的額外文件。

       --gen-suppressions= [default: no]
              當設置爲yes時,Valgrind將會在每一個錯誤顯示以後自動暫停而且打印下
              面這一行:
                  ---- Print suppression ? --- [Return/N/n/Y/y/C/c] ----


              這個提示的行爲和--db-attach選項(見下面)相同。

             若是選擇是,Valgrind會打印出一個錯誤的禁止條目,你能夠把它剪切而後
              粘帖到一個文件,若是不但願在未來再看到這個錯誤信息。

             當設置爲all時,Valgrind會對每個錯誤打印一條禁止條目,而不向用戶
              詢問。

             這個選項對C++程序很是有用,它打印出編譯器調整過的名字。

             注意打印出來的禁止條目是儘量的特定的。若是須要把相似的條目概括
              起來,好比在函數名中添加通配符。而且,有些時候兩個不一樣的錯誤也會
              產生一樣的禁止條目,這時Valgrind就會輸出禁止條目不止一次,可是在
              禁止條目的文件中只須要一份拷貝(可是若是多於一份也不會引發什麼問
              題)。而且,禁止條目的名字像<在這兒輸入一個禁止條目的名字>;名字並
              不是很重要,它只是和-v選項一塊兒使用打印出全部使用的禁止條目記錄。

       --db-attach= [default: no]
              當這個選項打開時,Valgrind將會在每次打印錯誤時暫停並打出以下
              一行:

                  ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ----

             按下回車,或者N、回車,n、回車,Valgrind不會對這個錯誤啓動調試器。

             按下Y、回車,或者y、回車,Valgrind會啓動調試器並設定在程序運行的
              這個點。當調試結束時,退出,程序會繼續運行。在調試器內部嘗試繼續
              運行程序,將不會生效。

             按下C、回車,或者c、回車,Valgrind不會啓動一個調試器,而且不會再
              次詢問。

             注意:--db-attach=yes與--trace-children=yes有衝突。你不能同時使用
              它們。Valgrind在這種狀況下不能啓動。

              2002.05:這是一個歷史的遺留物,若是這個問題影響到你,請發送郵件並
              投訴這個問題。

              2002.11:若是你發送輸出到日誌文件或者到網絡端口,我猜這不會讓你有
              任何感受。不須理會。

       --db-command= [default: gdb -nw %f %p]
              經過--db-attach指定如何使用調試器。默認的調試器是gdb.默認的選項
              是一個運行時擴展Valgrind的模板。 %f會用可執行文件的文件名替換,
              %p會被可執行文件的進程ID替換。

             這指定了Valgrind將怎樣調用調試器。默認選項不會由於在構造時是否檢
              測到了GDB而改變,一般是/usr/bin/gdb.使用這個命令,你能夠指定一些
              調用其它的調試器來替換。

             給出的這個命令字串能夠包括一個或多個%p %f擴展。每個%p實例都被
              解釋成將調試的進程的PID,每個%f實例都被解釋成要調試的進程的可
              執行文件路徑。             

       --input-fd= [default: 0, stdin]
              使用--db-attach=yes和--gen-suppressions=yes選項,在發現錯誤時,
              Valgrind會停下來去讀取鍵盤輸入。默認地,從標準輸入讀取,因此關閉
              了標準輸入的程序會有問題。這個選項容許你指定一個文件描述符來替代
              標準輸入讀取。

       --max-stackframe= [default: 2000000]
              棧的最大值。若是棧指針的偏移超過這個數量,Valgrind則會認爲程序是
              切換到了另一個棧執行。

             若是在程序中有大量的棧分配的數組,你可能須要使用這個選項。
              valgrind保持對程序棧指針的追蹤。若是棧指針的偏移超過了這個數量,
              Valgrind假定你的程序切換到了另一個棧,而且Memcheck行爲與棧指
              針的偏移沒有超出這個數量將會不一樣。一般這種機制運轉得很好。然而,
              若是你的程序在棧上申請了大的結構,這種機制將會表現得愚蠢,而且
              Memcheck將會報告大量的非法棧內存訪問。這個選項容許把這個閥值設置
              爲其它值。

             應該只在Valgrind的調試輸出中顯示須要這麼作時才使用這個選項。在這
              種狀況下,它會告訴你應該指定的新的閥值。

             廣泛地,在棧中分配大塊的內存是一個壞的主意。由於這很容易用光你的
              棧空間,尤爲是在內存受限的系統或者支持大量小堆棧的線程的系統上,
              由於Memcheck執行的錯誤檢查,對於堆上的數據比對棧上的數據要高效
              不少。若是你使用這個選項,你可能但願考慮重寫代碼在堆上分配內存
              而不是在棧上分配。

 

工做原理簡介:

valgrind被設計成非侵入式的,它直接工做於可執行文件上,所以在檢查前不須要從新編譯、鏈接和修改你的程序。要檢查一個程序很簡單,只須要執行下面的命令就能夠了

 

valgrind --tool=tool_name program_name

 

好比咱們要對ls -l命令作內存檢查,只須要執行下面的命令就能夠了

 

valgrind --tool=memcheck ls -l

 

無論是使用哪一個工具,valgrind在開始以前總會先取得對你的程序的控制權,從可執行關聯庫裏讀取調試信息。而後在valgrind核心提供的 虛擬CPU上運行程序,valgrind會根據選擇的工具來處理代碼,該工具會向代碼中加入檢測代碼,並把這些代碼做爲最終代碼返回給valgrind核 心,最後valgrind核心運行這些代碼。

 

不一樣工具間加入的代碼變化很是的大。在每一個做用域的末尾,memcheck加入代碼檢查每一片內存的訪問和進行值計算,代碼大小至少增長12倍,運行速度要比平時慢25到50倍。

 

valgrind模擬程序中的每一條指令執行,所以,檢查工具和剖析工具不只僅是對你的應用程序,還有對共享庫,GNU C庫,X的客戶端庫都起做用。

 

 

 

一些打印信息的解釋:

分析輸出的調試信息
==3908== Memcheck, a memory error detector.
==3908== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==3908== Using LibVEX rev 1732, a library for dynamic binary translation.
==3908== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==3908== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==3908== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==3908== For more details, rerun with: -v
==3908==
--3908-- DWARF2 CFI reader: unhandled CFI instruction 0:50
--3908-- DWARF2 CFI reader: unhandled CFI instruction 0:50
/*數組越界錯誤*/
==3908== Invalid write of size 4     
==3908==    at 0x8048384: f (test.c:6)
==3908==    by 0x80483AC: main (test.c:11)
==3908==  Address 0x400C050 is 0 bytes after a block of size 40 alloc'd
==3908==    at 0x40046F2: malloc (vg_replace_malloc.c:149)
==3908==    by 0x8048377: f (test.c:5)
==3908==    by 0x80483AC: main (test.c:11)
==3908==
==3908== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 14 from 1)
==3908== malloc/free: in use at exit: 40 bytes in 1 blocks.
==3908== malloc/free: 1 allocs, 0 frees, 40 bytes allocated.
==3908== For counts of detected errors, rerun with: -v
==3908== searching for pointers to 1 not-freed blocks.
==3908== checked 59,124 bytes.
==3908==
==3908==
/*有內存空間沒有釋放*/
==3908== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3908==    at 0x40046F2: malloc (vg_replace_malloc.c:149)
==3908==    by 0x8048377: f (test.c:5)
==3908==    by 0x80483AC: main (test.c:11)
==3908==
==3908== LEAK SUMMARY:
==3908==    definitely lost: 40 bytes in 1 blocks.
==3908==      possibly lost: 0 bytes in 0 blocks.
==3908==    still reachable: 0 bytes in 0 blocks.
==3908==         suppressed: 0 bytes in 0 blocks
相關文章
相關標籤/搜索