valgrind的介紹、安裝和使用

Valgrind manual:

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

 

valgrind介紹:

l   Valgrind查找內存泄露利器

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。下面分別介紹個工具的作用:

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)

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

 

 

 轉自:https://blog.csdn.net/justheretobe/article/details/52986461

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