valgrind +gdb 調試

Valgrind是一套Linux下,開放源代碼(GPL V2)的仿真調試工具的集合。Valgrind由內核(core)以及基於內核的其餘調試工具組成。內核相似於一個框架(framework),它模擬了一個CPU環境,並提供服務給其餘工具;而其餘工具則相似於插件 (plug-in),利用內核提供的服務完成各類特定的內存調試任務。Valgrind的體系結構以下圖所示:node

valgrind的結構圖linux

點擊看大圖

 

Valgrind包括以下一些工具:數組

 

 

  1. Memcheck。這是valgrind應用最普遍的工具,一個重量級的內存檢查器,可以發現開發中絕大多數內存錯誤使用狀況,好比:使用未初始化的內存,使用已經釋放了的內存,內存訪問越界等。這也是本文將重點介紹的部分。
  2. Callgrind。它主要用來檢查程序中函數調用過程當中出現的問題。
  3. Cachegrind。它主要用來檢查程序中緩存使用出現的問題。
  4. Helgrind。它主要用來檢查多線程程序中出現的競爭問題。
  5. Massif。它主要用來檢查程序中堆棧使用中出現的問題。
  6. Extension。能夠利用core提供的功能,本身編寫特定的內存調試工具

linux下內存空間佈置:

典型內存空間佈局

下面下valgrind 中memcheck 和callgrind 的簡單使用;--db-attach=yes 能夠在發現問題的時候進入緩存

gdb調試,注意通過實踐發現隨着memcheck,callgrind option 越多將影響內存分佈,多線程調用順序.使得畢現的crash變成偶現,或者偶現問題變得畢現.多線程

下面是valgrind 對內存reachable的分類及說明,根據valgrind output 中內存泄露的類型能夠預測app

內存丟失的場景.框架

Pointer chain            AAA Leak Case   BBB Leak Case
     -------------            -------------   -------------
(1)  RRR ------------> BBB                    DR
(2)  RRR ---> AAA ---> BBB    DR              IR
(3)  RRR               BBB                    DL
(4)  RRR      AAA ---> BBB    DL              IL
(5)  RRR ------?-----> BBB                    (y)DR, (n)DL
(6)  RRR ---> AAA -?-> BBB    DR              (y)IR, (n)DL
(7)  RRR -?-> AAA ---> BBB    (y)DR, (n)DL    (y)IR, (n)IL
(8)  RRR -?-> AAA -?-> BBB    (y)DR, (n)DL    (y,y)IR, (n,y)IL, (_,n)DL
(9)  RRR      AAA -?-> BBB    DL              (y)IL, (n)DL

Pointer chain legend:
- RRR: a root set node or DR block
- AAA, BBB: heap blocks
- --->: a start-pointer
- -?->: an interior-pointer

Leak Case legend:
- DR: Directly reachable
- IR: Indirectly reachable
- DL: Directly lost
- IL: Indirectly lost
- (y)XY: it's XY if the interior-pointer is a real pointer
- (n)XY: it's XY if the interior-pointer is not a real pointer
- (_)XY: it's XY in either case

Every possible case can be reduced to one of the above nine. Memcheck merges some of these cases in its output, resulting in the following four leak kinds.less

  • "Still reachable". This covers cases 1 and 2 (for the BBB blocks) above. A start-pointer or chain of start-pointers to the block is found. Since the block is still pointed at, the programmer could, at least in principle, have freed it before program exit. "Still reachable" blocks are very common and arguably not a problem. So, by default, Memcheck won't report such blocks individually.dom

  • "Definitely lost". This covers case 3 (for the BBB blocks) above. This means that no pointer to the block can be found. The block is classified as "lost", because the programmer could not possibly have freed it at program exit, since no pointer to it exists. This is likely a symptom of having lost the pointer at some earlier point in the program. Such cases should be fixed by the programmer.ide

  • "Indirectly lost". This covers cases 4 and 9 (for the BBB blocks) above. This means that the block is lost, not because there are no pointers to it, but rather because all the blocks that point to it are themselves lost. For example, if you have a binary tree and the root node is lost, all its children nodes will be indirectly lost. Because the problem will disappear if the definitely lost block that caused the indirect leak is fixed, Memcheck won't report such blocks individually by default.

  • "Possibly lost". This covers cases 5--8 (for the BBB blocks) above. This means that a chain of one or more pointers to the block has been found, but at least one of the pointers is an interior-pointer. This could just be a random value in memory that happens to point into a block, and so you shouldn't consider this ok unless you know you have interior-pointers.

(Note: This mapping of the nine possible cases onto four leak kinds is not necessarily the best way that leaks could be reported; in particular, interior-pointers are treated inconsistently. It is possible the categorisation may be improved in the future.)

Furthermore, if suppressions exists for a block, it will be reported as "suppressed" no matter what which of the above four kinds it belongs to.

Example:

note: --trace-origins= yes 在memcheck 中能夠用來追蹤被使用的未初始化數據,是在什麼時候建立分配的.

valgrind --trace-children=yes --tool=memcheck  --show-reachable=yes --leak-check=full --keep-stacktraces=alloc-then-free --db-attach=yes ./x264 -v   --pass 1 --bitrate 2000 -o test.264 --input-res 1280x720 --input-csp i420 ./1280_720_frame_10.yuv 

 

 

 

 


 

callgrind:

下面是一個callgrind 的的調用截圖,callgrind 的check結果默認會保存在callgrind.out.pid 問題件中.

若是你調試的程序是多線程,你也能夠在命令行中加一個參數 -separate-threads=yes。這樣就會爲每一個線程單獨生成一個性能分析文件。以下:

valgrind --tool=callgrind --separate-threads=yes ./app

 

valgrind --trace-children=yes --tool=callgrind   --db-attach=yes ./x264 -v   --pass 1 --bitrate 2000 -o test.264 --input-res 1280x720 --input-csp i420 ./1280_720_frame_10.yuv 

1,運行命令,能夠從命令打印中看出下個版本db-attach 將被--vgdb-error=1 取代.

2,valgrind 檢測處問題,詢問是否啓動gdb ?按鍵c 繼續不起懂,按鍵y 啓動gdb調試

3,按鍵y 進入gdb 調試,看出可能在數組定義的時候出現問題

4,查看當前backtrace 中fram 0 的源碼.

5,打印nal_unit_type_str 發現定義了13 個char* ,只初始化了11個.

 

 

 

 

雜記:

show commands 能夠助記以前的命令.

相關文章
相關標籤/搜索