valgrind-yyds——memcheck检查程序中的内存问题,如泄漏、越界、非法指针等。
Valgrind 用戶手冊
文章目錄
- 1. valgrind概述
- 2. Valgrind 原理及安裝
- 2.1 [Valgrind 做了什么](https://www.valgrind.org/docs/manual/manual-core.html)
- 2.2 安裝
- 3 內(nèi)存檢測
- 3.1 memcheck 常用檢測指令
- 3 .2 內(nèi)存檢測結(jié)果
- 3 .3 內(nèi)存檢測含義
- 3 .4 內(nèi)存檢測更多例子
1. valgrind概述
Valgrind 是用于構(gòu)建動態(tài)分析工具的檢測框架。它帶有一組工具,每個工具都執(zhí)行某種調(diào)試、分析或類似任務(wù),以幫助您改進(jìn)程序。Valgrind 的架構(gòu)是模塊化的,因此可以輕松創(chuàng)建新工具,而不會干擾現(xiàn)有結(jié)構(gòu)。
- Memcheck是一個內(nèi)存錯誤檢測器。它可以幫助您使您的程序,尤其是那些用 C 和 C++ 編寫的程序更加正確。
- Cachegrind是一個緩存和分支預(yù)測分析器。它可以幫助您使程序運行得更快。
- Callgrind是一個調(diào)用圖生成緩存分析器。它與 Cachegrind 有一些重疊,但也收集了一些 Cachegrind 沒有的信息。
- Helgrind是一個線程錯誤檢測器。它可以幫助您使多線程程序更加正確。
- DRD也是一個線程錯誤檢測器。它類似于 Helgrind,但使用不同的分析技術(shù),因此可能會發(fā)現(xiàn)不同的問題。
- Massif是一個堆分析器。它可以幫助您使程序使用更少的內(nèi)存。
- DHAT是一種不同的堆分析器。它可以幫助您了解塊生命周期、塊利用率和布局效率低下的問題。
- BBV是一個實驗性的 SimPoint 基本塊向量生成器。它對從事計算機體系結(jié)構(gòu)研究和開發(fā)的人很有用。
2. Valgrind 原理及安裝
2.1 Valgrind 做了什么
一方面,Memcheck 添加了代碼來檢查每次內(nèi)存訪問和計算的每個值,使其運行速度比本機慢 10-50 倍。
另一種工具,稱為 Nulgrind 的最小工具根本不添加任何儀器,并且總共“僅”導(dǎo)致大約 4 倍的減速。
Valgrind 模擬程序執(zhí)行的每一條指令。因此,活動工具不僅會檢查或分析應(yīng)用程序中的代碼,還會檢查所有支持動態(tài)鏈接的庫,包括 C 庫、圖形庫等。
如果您正在使用錯誤檢測工具,Valgrind可以檢測系統(tǒng)庫中的錯誤,例如您必須使用的GNU C或X11庫。您可能對這些錯誤不感興趣,因為您可能無法控制這些代碼。因此,Valgrind允許您選擇性地抑制錯誤
you can use the --gen-suppressions=yes option.指示Valgrind讀取描述內(nèi)聯(lián)信息的調(diào)試信息。這樣,就可以正確地顯示函數(shù)調(diào)用鏈,即使您的應(yīng)用程序是用內(nèi)聯(lián)方式編譯的。
2.2 安裝
建議從valgrind官網(wǎng)下載安裝,目前官網(wǎng)的最新包是3.16.1
$ mkdir valgrind-inst
$ cd valgrind-inst/
$ wget https://sourceware.org/pub/valgrind/valgrind-3.16.1.tar.bz2$ ls
valgrind-3.16.1.tar.bz2
//解壓后進(jìn)行安裝,可以指定安裝目錄,這樣的話記得設(shè)置環(huán)境變量
$ tar -xvf valgrind-3.16.1.tar.bz2
$ cd valgrind-3.16.1
$ ./configure --prefix=/usr/local/valgrind
$ make
$ make install
查看是否安裝成功
$ valgrind --version
valgrind-3.16.1
3 內(nèi)存檢測
3.1 memcheck 常用檢測指令
最常用的工具,用來檢測程序中出現(xiàn)的內(nèi)存問題,所有對內(nèi)存的讀寫都會被檢測到,一切對malloc、free、new、delete的調(diào)用都會被捕獲。所以,它能檢測以下問題:
1、使用未初始化的內(nèi)存。如果在定義一個變量時沒有賦初始值,后邊即使賦值了,使用這個變量的時候Memcheck也會報"uninitialised value"錯誤。使用中會發(fā)現(xiàn),valgrind提示很多這個錯誤,由于關(guān)注的是內(nèi)存泄漏問題,所以可以用--undef-value-errors=選項把這個錯誤提示屏蔽掉,具體可以看后面的選項解釋。2、讀/寫釋放后的內(nèi)存塊;3、內(nèi)存讀寫越界(數(shù)組訪問越界/訪問已經(jīng)釋放的內(nèi)存),讀/寫超出malloc分配的內(nèi)存塊;4、讀/寫不適當(dāng)?shù)臈V袃?nèi)存塊;5、內(nèi)存泄漏,指向一塊內(nèi)存的指針永遠(yuǎn)丟失;6、不正確的malloc/free或new/delete匹配(重復(fù)釋放/使用不匹配的分配和釋放函數(shù));7、內(nèi)存覆蓋,memcpy()相關(guān)函數(shù)中的dst和src指針重疊。
valgrind --tool=memcheck --leak-check=full ./build/bin/aurora300_runner
valgrind --leak-check=full --show-leak-kinds=all ./build/bin/aurora300_runner
編譯后,用valgrind檢測程序。
如果設(shè)置了–leak-check=full,Memcheck會給出詳細(xì)的每個塊是在哪里分配,并且給出分配時函數(shù)調(diào)用堆棧(編譯的時候使用**-g選項**和去掉-o優(yōu)化選項,就可以得到更詳細(xì)的函數(shù)信息,可以精確到代碼的某一行)。可以通過–show-leak-kinds選項來選擇要詳細(xì)報告哪幾種類型的錯誤。Memcheck會把函數(shù)調(diào)用堆棧相同或相似的內(nèi)存塊信息,放到同一個條目來顯示,可以通過–leak-resolution來控制這個"相似"判斷的力度。
--tool: 是最常用的選項,用于選擇使用valgrind工具集中的哪一個工具。默認(rèn)值為memcheck。--version: 用于打印valgrind的版本號-q/--quiet: 安靜的運行,只打印錯誤消息;-v/--verbose: 打印更詳細(xì)的信息;--trace-children: 是否跟蹤子進(jìn)程,默認(rèn)值為no;--track-fds: 是否追蹤打開的文件描述符,默認(rèn)為no--time-stamp=no|yes: 是否在打印出的每條消息之前加上時間戳信息。默認(rèn)值為no--log-file=<file>: 指定將消息打印到某個文件--default-suppressions: 加載默認(rèn)的抑制參數(shù)。--alignment: 指定malloc分配內(nèi)存時的最小對齊字節(jié)數(shù);如下的一些選項用于Memcheck工具:--leak-check=no|summary|full: 在退出時是否查找內(nèi)存泄露。默認(rèn)值為summary--show-leak-kinds=kind1,kind2,..: 顯示哪一種類型的內(nèi)存泄露。默認(rèn)顯示definite和possible這兩種;
3 .2 內(nèi)存檢測結(jié)果
output:
HEAP SUMMARY:
==6018== in use at exit: 10 bytes in 1 blocks
==6018== total heap usage: 1 allocs, 0 frees, 10 bytes allocated
==6018==
==6018== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6018== at 0x4C2AC58: operator new[](unsigned long) (vg_replace_malloc.c:431)
==6018== by 0x40062E: func() (leak.cpp:4)
==6018== by 0x40063D: main (leak.cpp:8)
==72970== LEAK SUMMARY:
==72970== definitely lost: 0 bytes in 0 blocks
==72970== indirectly lost: 0 bytes in 0 blocks
==72970== possibly lost: 61,552 bytes in 71 blocks
==72970== still reachable: 152,585 bytes in 2,436 blocks
==72970== of which reachable via heuristic:
==72970== newarray : 792 bytes in 3 blocks
==72970== suppressed: 0 bytes in 0 blocks
==72970== Reachable blocks (those to which a pointer was found) are not shown.
==72970== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==72970==
==72970== For counts of detected and suppressed errors, rerun with: -v
==72970== Use --track-origins=yes to see where uninitialised values come from
==72970== ERROR SUMMARY: 70078 errors from 51 contexts (suppressed: 0 from 0)
3 .3 內(nèi)存檢測含義
結(jié)果說明:
先看看輸出信息中的HEAP SUMMARY,它表示程序在堆上分配內(nèi)存的情況,其中的1 allocs 表示程序分配了 1 次內(nèi)存,0 frees表示程序釋放了 0 次內(nèi)存,10 bytes allocated表示分配了 10 個字節(jié)的內(nèi)存。 另外,Valgrind 也會報告程序是在哪個位置發(fā)生內(nèi)存泄漏。
上面LEAK SUMMARY會打印5種不同的類型,這里我們簡單介紹一下:
結(jié)果說明:
- definitely lost:
明確丟失的內(nèi)存。程序中存在內(nèi)存泄露,應(yīng)盡快修復(fù)。當(dāng)程序結(jié)束時如果一塊動態(tài)分配的內(nèi)存沒有被釋放并且通過程序內(nèi)的指針變量均無法訪問這塊內(nèi)存則會報這個錯誤; - indirectly lost:
間接丟失。當(dāng)使用了含有指針成員的類或結(jié)構(gòu)體時可能會報這個錯誤。這類錯誤無需直接修復(fù),它們總是與definitely lost一起出現(xiàn),只要修復(fù)definitely lost即可。 - possibly lost:
可能丟失。大多數(shù)情況下應(yīng)視為與definitely lost一樣需要盡快修復(fù),除非你的程序讓一個指針指向一塊動態(tài)分配的內(nèi)存(但不是這塊內(nèi)存的起始地址),然后通過運算得到這塊內(nèi)存的起始地址,再釋放它。當(dāng)程序結(jié)束時如果一塊動態(tài)分配的內(nèi)存沒有被釋放并且通過程序內(nèi)的指針變量均無法訪問這塊內(nèi)存的起始地址,但可以訪問其中的某一部分?jǐn)?shù)據(jù),則會報這個錯誤。 - still reachable:
可以訪問,未丟失但也未釋放。如果程序是正常結(jié)束的,那么它可能不會造成程序崩潰,但長時間運行有可能耗盡系統(tǒng)資源。
3 .4 內(nèi)存檢測更多例子
總結(jié)
以上是生活随笔為你收集整理的valgrind-yyds——memcheck检查程序中的内存问题,如泄漏、越界、非法指针等。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【NEON 】初探
- 下一篇: valgrind——Cachegrind