VisualStudio 的視覺化偵錯工具:Graphical Debugging

| | 0 Comments| 14:19
Categories:

「Graphical Debugging」(網頁)是 VisualStudio 的一個延伸模組,它的功能是可以把 C++ 與 C# 中特並類型的資料、視覺畫出來、方便在偵錯的時候觀察。官方的說明是:

Visualization of C++ and C# variables during debugging, e.g. Boost.Geometry models, containers of values, arrays of points, etc.

Heresy 最早看到是很久以前的「Boost Debugger visualizers」(網頁),最初應該是只有針對 Boost C++ Libraries 的型別來做監看的修飾,但是看來現在功能多了很多了~

Graphical Debugging 的功能主要分成四大類:

  • Debugger visualizers
    • 針對 Boost.Array、Boost.Container、Boost.Geometry、Boost.MPL、Boost.Polygon、Boost.Tuple 和 Boost.Variant 這些型別的資料,調整在 VisualStudio 偵錯時、監看視窗所顯示的內容格式,讓他顯示地更友善。
  • Geometry Watch
    • 將 2D 幾何資料用畫出來觀察。
      可以同時顯示多組資料,所以可以更方便地以視覺化的方法來比較資料。
    • 支援 Boost.Geometry 或 Boost.Polygon 這類的資料。
  • Graphical Watch
    • 以表格的形式,將多組變數用圖形的方式來個別表示。
    • 支援 Boost.Geometry 或陣列。
  • Plot Watch
    • 把多組變數同時畫出來,進行觀察、比較。

其中,第一項 Debugger visualizers 在 VisualStudio 中並沒有額外的介面,但是後面三個,則是都有獨立的視窗介面,可以在 VIsualStudio 的「檢視」、「其他視窗」中找到。

下面就是官方提供的三個視窗的範例圖:

實際上,Geometry Watch 和 Plot Watch 的界面並沒有太大的不同,兩者都可以在同一個座標系統中顯示多組資料以進行比對,主要是針對呈現資料的性質有些差異。

而 Graphical Watch 在介面上就比較不一樣了,它可以同時顯示 Geometry Watch 和 Plot Watch 能顯示的資料,只是差別在於它是用表格的形式、一筆一筆資料會是獨立顯示的。


在支援的資料格式的部分,在網頁上算是有相當完整的列表。

基本上,他主要支援 Boost 和 STL 的資料,也支援 C-style 的陣列、或是陣列指標。
而在幾何的部分,主要就還是以 Boost.Geometry 和 Boost.Polygon 為主了;其他自訂型別、或是別的函式庫的資料要拿來用,可能會比較有難度。

由於 Heresy 沒有在使用 Boost.Geometry 和 Boost.Polygon,所以這邊 Heresy 在玩的時候,主要是以 Plot Watch 為主。

使用時,基本上就是在偵錯的時候,透過「檢視」、「其他視窗」裡的選項,來叫出「Plot Watch」的視窗。

右圖就是他的介面。上面是用來繪製資料的區域,下面則是顯示資料的列表。

要加入顯示的資料的話,基本上就是在下方表格的「Name」的欄位中,輸入變數的名稱;這樣他就會在後面顯示資料的類型、並自動賦予一個顏色。

而如果這組資料是他可以顯示的話,上面就會出現對應的圖形了。

右圖所呈現的資料有四組,其中 af1,5 是一維陣列、所以是以 bar chart 來顯示;vf1,10;f2,10 則是代表二維陣列,是用一個點一個點來描繪的。

而這些資料的個別型態,可以參考下面的測試程式碼:

#include <map>
#include <array>
#include <vector>
int main()
{
  float* f1 = new float[10]{ 1,2,3,4,5,6,7,8,9,10 };
  float* f2 = new float[10]{ 1,2,3,4,5,6,7,8,9,10 };
  std::array<float, 10> a{ 10,9,8,7,6,5,4,3,2,1 };
  std::vector<std::pair<float, float>> v;
  for (int i = 0; i < 50; ++i)
  {
    float f = 0.1f * i;
    v.push_back({ f, sin(f) });
  }
  return 0;
}

在這邊,a 是直接使用 std::array<>,應該沒什麼問題;其他像是 vectorlistdeque 等,也都是支援的。

v 則是 std::vector<std::pair<float,float>> 來代表一連串的 2D 點;這邊之所以使用 std::pair<> 來代表單一點位,主要是因為 Graphical Debugging 能支援的點的類型,基本上只有下面這些:

  • STL: complex, pair
  • Boost.Geometry: point, point_xy
  • Boost.Polygon: point_data

那其他的資料要怎麼畫呢?針對一般性的資料陣列,Graphical Debugging 可以透過簡單的語法,來進一步描述資料來做繪製。

f1,5 來說,f1 就是一個指到大小為 10 的浮點數陣列的指標;而在後面加上「,5」,就是告訴 Graphical Debugging 把它視為一個大小是 5 的陣列,也就是說拿他的前五個數字來做繪製。其結果就是一個 bar chart。

f1,10;f2,10 則是把 f1,10f2,10 個別視為一個大小為 10 的陣列,然後把兩個放在一起、當作一個二微陣列來繪製;所以它的結果,就會類似 v,變成是以點組成的圖形。

透過這種直接去存取指標的方法,在某方面來說,應該也算是稍微增加了 Graphical Debugging 的使用彈性。


而同樣的資料,在 Geometry Watch、Graphical Watch 在 Plot Watch 中的話,他的呈現效果大概會是下面的樣子:

其中,由於 Geometry Watch 並不支援一維陣列的 bar chart,所以 a 是畫不出來。

另外,Plot Watch 因為不支援幾何圖形,所以如果有用到 Boost.Geometry 的話,那他也會畫不出來。


整體來說,個人覺得這個套件在某些情況下,應該算是滿實用的!由於是要針對計算的結果來找問題的時候,如果能把他們畫出來,有的時候是很方便的~

但是相對地,他的缺點是他主要支援 STL 和 Boost,而除了預設有支援的類別外,似乎並沒有提供比較大的客製化彈性;所以如果是使用自定義的型別的話,Graphical Debugging 似乎就完全沒用了…

最後,Graphical Debugging 和之前介紹過的「ImageWatch」有點類似,不過 ImageWatch 能呈現的主要是「圖片」,而 Graphical Debugging 則是把資料畫出來,其實在對應的資料的性質上還是不同的。

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *