壹、自動變數
在 逐步 Trace 之概述裡面有提到,呼叫監看視窗是以「自動變數」方式觀查,
但實際上用自動變數非常不方便觀查,
因自動變數 scope 變化甚大,很可能只顯示一行指令裡,用到的變數值而已。
假設 程式碼以下述為例。
1. 一開始便以逐步 trace (F10) 方式進行時,在進入 main 時, debug 視窗如下
2. 再按一次 F10,自動變數裡面只有 a, b
3. 再按一次 F10,這次多了變數 c。
4. 這次多了 d 出來。
欲觀查之變數欄位不固定,這在 debug 並不會非常方便,通常是把要觀查的變數直接列出來便可。
這裡用到的是「監看式」。
貮、監看式
一樣的程式碼,這次固定去觀查某些變數值,比如說一次觀查 a, b, c, d, e ,不要讓欄位跳來跳去的。
1. 在進入偵錯模式時, 按下「偵錯 -> 監看式 -> 監看式1」,也許輸出視窗裡面已經有此視窗了。
2. 直接在監看式名稱裡面輸入 a
3. 第二種方式,假設要觀查 b,先找一個有 b 變數的地方,按右鍵
再選擇「加入監看式」
上面兩種方法都可加入監看式,但用輸入方式會較好,因還可以指定類似 *p、&p、array[0] 這種東西。
4. 全弄好後,監看式大概長這樣,會有那些錯誤,是因還沒執行到該行,整個程式看不到該變數之 scope。
5. 接下來此監看式欄位都一樣,剩下的是觀查變數的狀態而已。
6. 其實監看式也不只一個視窗可以看,目前我看是可以看到四個視窗之監看式,可按下「偵錯->視窗->監看式」,再呼叫其它監看式。
7. 如下所示,我把不同 scope 之變數,納到不同監看式裡去。監看式分類之技巧看個人而定,有些人習慣只用一個監看式,有些人用 scope 去分監看式,另也有些人依 function 去分監看式,這部份依看人習慣及問題大小、變數多寡而定。
參、利用監看式更改記憶體內容值
這技巧常用到 bounding check ,以確保在 bounding 時程式不會出錯。
考慮以下程式碼及斷點位置
#include <stdio.h> int main() { int a=10, b=5; int *pa=&a; int *pb=&b; printf(" a=%d, b=%d\n", a, b ); printf("*pa=%d, *pb=%d\n", *pa, *pb); printf(" a=%d, b=%d\n", a, b ); // break point printf("*pa=%d, *pb=%d\n", *pa, *pb); getchar(); return 0; }
以下動作,我們將會透過監看式,將 a, b 值改為 100 與 200。
1. 執行後,監看式先加入 a, b, pa, pb 變數。
2. 注意到 pa 與 pb 是可以展開的,先將它們展開。
由於 pa , pb 為 pointer to object,所以只會展開一層;相對的,如果為 pointer to pointer to object,這樣就會展開兩層。
3. 快點 a 之值二下,改成 100
仔細觀查 pa 展開之處,由於 pa 指向 a,所以在監看式裡, *pa 也會跟著變。
4. 快點 pb 之值二下 (不要改到 address),改成 200
由於 pb 指向 b,所以改過之後 b 之值也會跟著變。
5. 再按一次 F5 執行,結果便如下所視。
6. 於監看式加入其他運算式
監看式不只可以觀查變數變化,事實上與一般在寫 C/C++ code 時沒什麼兩樣,比如說還要再觀查測試 a*b、a/b 之值。
甚至還可以再加入 &a、&b 等等,這些都看有沒有需求之必要。