VC++6.0調試:Watch窗口的使用


 1 #include <stdio.h>
 2 #include <windows.h>
 3 
 4 class AutoExpand
 5 {
 6 public:
 7     AutoExpand(int val, char* pval)
 8     {
 9         a = val;
10         p = pval;
11     }
12 private:
13     int a;
14     char *p;
15 };
16 class CantExpand
17 {
18 public:
19     CantExpand(int val, char* pval)
20     {
21         a = val;
22         p = pval;
23     }
24 private:
25     int a;
26     char *p;
27 };
28 
29 int main(void)
30 {
31     int p[4] = {0x31,0x32,0x33,0x34};
32     int *a  = p;
33     
34     FILE* fp = fopen("File Not Exist", "r");
35     DWORD dwError = GetLastError();
36     
37     AutoExpand ae(10, "abc");
38     CantExpand ce(10, "abc");
39 
40     return 0;
41 }

      上面代碼中出現的變量先說明一下:

  p: 是整形數組,含四個元素,總共16Byte;

  a: 整形指針,指向數組p;

  fp: 文件指針,用來標識打開的"File Not Exist",我機器里是沒這個文件的;

  dwError: 獲得fopen失敗的錯誤碼。一般來說可以用FormatMessge來格式化這個錯誤原因或者直接用VC自帶的工具errorlookup來查找這個錯誤碼的解釋;

  ae和ce: 是自定義的AutoExpand類型的變量和CantExpand類型的變量。注意,這兩種類型只有類型名字不同。

  下面看一下我在調試這個程序的時候,watch窗口的顯示:

  

  上圖中,左邊是Context窗口的Locals頁,顯示所有局部變量。右邊是Watch窗口,是我自己添加的要觀察的對象。 

  好,先看看整形數組p。我們看到Context窗口的顯示p其實只顯示了數組的地址,點了+號展開后,顯示出了4個整形數據。而右邊窗口,我添加了一個p,c。p后面加個",c"是什么意思呢?看看效果,p,c下面的[0],[1],[2],[3]顯示的是這4個整形值對應的ascii字符哈。所以從這里有了第一個小技巧:

  1.watch窗口中,在整形變量后面加上",c"可以顯示該變量對應的ASCII字符。實際上,可以直接敲數字這么顯示也行。比如上面右邊窗口中的118,c的對應值是'v'。也就是說118對應的ASCII字符是'v'。那么,反過來,要知道一個字符的ASCII碼值怎么看呢?看上面,'v',d就是顯示字符'v'對應的十進制ASCII碼值是118。 'v',x顯示的是對應的十六進制的ASCII碼值。除了",c"   ",d"   ",x"外,還有一些其他的參數可以加,見后面的附表。

  然后我們看看變量a。a是個指針。看左邊窗口,即使點了它的+號展開,也只看到了它指向的地址的第一個元素(49)。如果想要看得更多的數據,也可以像我一樣,在上面的Memory窗口里看。但是Memory窗口只有一個,要看多個指針指向的數據就麻煩了,切來切去。那就在watch窗口中顯示吧,a,4就可以了,看到我的watch窗口的顯示沒?所以,有了第二個小技巧:

  2.watch窗口中,把指針當成數組看,只要在指針名后面加上一個長度,就可以想看數組一樣看到對應的數據了。比如我上面的a,4。那么如果一個指針指向的數據很大,比如一個整形指針a是指向一個1000個整數的大塊內存,我只想看看最后4個數據,要怎樣呢?那就(a+996),4 唄。從第996個數據開始,看4個~

  接下來這個小技巧是我最喜歡的一個了。調試中遇到系統函數調用失敗的情況,通常都要加上GetLastError()函數獲得返回值,然后查對應的解釋才知道錯誤原因。比如,我上面的代碼要打開一個不存在的文件,結果fopen失敗。取回了錯誤碼dwError=2,一查才知道是文件不存在。那么可不可以不用查,調試器直接告訴我原因呢?當然可以,不然我寫這干嘛!剛才的錯誤碼2是記錄在dwError中了,所以只要在watch窗口看看dwError,hr看value欄:系統找不到指定的文件!爽吧!總結一下,第三個小技巧:

  3. 在watch窗口中察看錯誤原因,只需要在錯誤之后面頰上",hr"就可以了。比如我上面的 dwError,hr 和 2, hr 都能夠顯示錯誤消息。想看某個錯誤碼的解釋,只要后面加上",hr"就輕松搞定,非常方便!這里還要提一下的是,即使不調用GetLastError()也是可以看錯誤原因的。在fopen()調用完后,直接在watch窗口敲err,hr也可以顯示最近一次的錯誤原因。但是我機器重新裝了os,還沒裝vc,現在用的還是安裝前的屍體。所以這個err,hr的顯示有問題。不過還是有應對之法,那就是強大的TIB信息。watch窗口看看*(unsigned long*)(TIB+0x34), hr也是一樣的。至於為什么嗎,那就是GetLastError的機制了。

  還剩2個變量,ae和ce。這兩變量類型名不同,但是其他全都一樣。為什么這兩個變量在watch窗口中顯示的不一樣呢?ae直接顯示出了類成員的值,ce就顯示了個......嗯,這就是最后一個小技巧:

  4. 在vc安裝目錄的msdev\bin目錄下有個autoexp.dat文件。可以在里面自定義數據的顯示。具體的看看它前面的大段說明,說得很詳細。我就是在文件后面加上一行AutoExpand =int_val=<a,d> sz_val=<p,s>。

 

附表:

  下表說明調試器可識別的格式說明符。

 

說明符 格式 顯示
d,i signed 十進制整數 0xF000F065 -268373915
u unsigned 十進制整數 0x0065 101
o unsigned 八進制整數 0xF065 0170145
x,X 十六進制整數 61541(十進制) 0x0000F065
l,h 用於 d、i、u、o、x、X 的 long 或 short 前綴 00406042,hx 0x0c22
f signed 浮點型 3./2. 1.500000
e signed 科學計數法 3./2. 1.500000e+000
g signed 浮點型或 signed 科學計數法,無論哪個都更短 3./2. 1.5
c 單個字符 0x0065 101 'e'
s 字符串 0x0012fde8 "Hello world"
su Unicode 字符串   "Hello world"
hr HRESULT 或 Win32 錯誤代碼。(調試器自動將 HRESULT 解碼,因此這些情況下不需要該說明符。 0x00000000L S_OK
wc 窗口類標志。 0x00000040 WC_DEFAULTCHAR
wm Windows 消息數字 0x0010 WM_CLOSE

 

  下表包含用於內存位置的格式化符號。

符號 格式 顯示
ma 64 個 ASCII 字符 0x0012ffac .4...0...".0W&.......1W&.0.:W..1...."..1.JO&.1.2.."..1...0y....1
m 以十六進制表示的 16 個字節,后跟 16 個 ASCII 字符 0x0012ffac B3 34 CB 00 84 30 94 80 FF 22 8A 30 57 26 00 00 .4...0...".0W&..
mb 以十六進制表示的 16 個字節,后跟 16 個 ASCII 字符 0x0012ffac B3 34 CB 00 84 30 94 80 FF 22 8A 30 57 26 00 00 .4...0...".0W&..
mw 8 個字 0x0012ffac 34B3 00CB 3084 8094 22FF 308A 2657 0000
md 4 個雙倍字長 0x0012ffac 00CB34B3 80943084 308A22FF 00002657
mq 2 個四倍字長 0x0012ffac 7ffdf00000000000 5f441a790012fdd4
mu 2 字節字符 (Unicode) 0x0012fc60 8478 77f4 ffff ffff 0000 0000 0000 0000

  可以使用帶有計算為位置的任何值或表達式的內存位置說明符。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM