1. 程式人生 > >Delphi應用程序的調試(三)監視變量

Delphi應用程序的調試(三)監視變量

ron 代碼優化 不能 編輯器 十進制數 測試程序 對象 syn 實例

監視變量(Watching Variables)

當程序停在一個斷點處時,用戶做些什麽呢?通常用戶在斷點處停下來是要檢查變量的值,某個變量的值是否與預料的取值相同?或者某個變量取什麽值(事先並不知道這個變量的取值)。

Watch List窗口的作用是使用戶能檢查變量的值。編程人員常常忽視這個簡單而又根本的特性,因為他們沒有花時間來完整地學習調試器的使用。用戶可添加任意多的變量到Watch List中。下圖就是調試會話期間的Watch List窗口。

技術分享圖片

變量名和變量值都顯示在Watch List中。

Tooltip表達式求值(Tooltip Expression Evaluation)

調試器和Code Editor有一個很好的特性,它使檢查變量值的工作變得更容易。這個特性就是Tooltip表達式求值器(expression evaluator),其缺省狀態是打開,因此用戶不需要做任何事情就能使用它。如果需要,也可以通過Editor Properties對話框的Code Insight頁面來關閉它,如下圖:

技術分享圖片

那麽,什麽是Tooltip表達式求值呢?它是這樣工作的:當程序停在一個斷點處,用戶把編輯光標移到一個變量上,就會彈出一個提示窗口,其中顯示該變量的當前值。這樣就使快速檢查變量的工作變得更容易,只需將光標移到變量上並稍等片刻。

Tooltip evaluator求值器對於不同的變量類型由不同的顯示。對於常規數據成員(Integer、Char、Byte、String等等),顯示變量的實際值;對於動態創建的對象(例如一個類的實例),Tooltip evaluator顯示記錄的全部元素。如下圖所示:

技術分享圖片

技術分享圖片

Note

有時候Tooltip evaluator好像工作不正常。例如,若將編輯光標移到一個作用域外的變量上時,就不會顯示提示窗口,因為Tooltip evaluator 無任何信息可顯示。被編輯器優化過的變量也可能不能顯示正確值。

當光標位於with塊中時,Tooltip evaluator也不工作。例如,看下面這段代碼:

1 2 3 4 5 6 7 8 9 10 11 var pp: Point; begin with pp do begin x := 20; y := 40;
end; Caption := IntToStr(pp.x); end;

如果把光標放到變量x上,Tooltip evaluator不會顯示x的值,因為x屬於with語句(Point變量)。如果將光標移到變量Point上,調試器會顯示Point的值(包括x字段)。如下圖:

技術分享圖片

Tooltip 表達式求值器很有用的,別忘記使用它。

Watch List快捷菜單(The Watch List Context Menu)

正如前面講到的每一個Delphi窗口一樣,Watch List也有它自己的快捷菜單。如下描述:

技術分享圖片

Edit Watch——打開Watch Properties對話框修改監視項屬性
Add Watch——打開Watch Properties對話框新監視項
Enable Watch——啟用一個已經禁用的監視項
Disable Watch——禁用一個已啟用的監視項
Delete Watch——刪除一個監視項
Enable All Watches——啟用所有已經禁用的監視項
Disable All Watches——禁用所有已經啟用的監視項
Delete All Watches——刪除所有監視項
Add Group——增加一個監視組
Delete Group——刪除一個監視組
Move Watch to Group——移動監視項到組
Stay On Top——使Watch List窗口始終在最上層

Inspect——顯示選中的監視項的有關信息
Break When Changed——當監視窗口中的變量改變時,調試器將終端。監視變量以紅色顯示,表示Break When Changed起作用。
Dockable——窗口是可泊位。

使用Watch Properties對話框(Using the Watch Properties Dialog Box)

技術分享圖片

當用戶增加或編輯監視項時,要使用Watch Properties對話框。如上圖顯示的是正在編輯pp變量的Watch Properties對話框。

位於對話框頂部的【Expression字段】,是用戶輸入要編輯或增加到Watch List中的變量名的地方,這個字段是一個組合框,可以用來選取以前用過的監視項。

但用戶要檢查數組時,使用【Repeat count字段】,比如,有一個20個整數元素的數組,要檢查數組的頭10個整數,可在【Expression字段】中輸入數組的第一個元素(例如Array[0]),再在【Repeat count字段】中輸入10。數組的頭10個元素就會顯示在Watch List中。如下圖pp為有20個元素的整型數組:

技術分享圖片

Note

如果將數組名增加到Watch List中,則數組的全部元素都會顯示在Watch List中。當要查看數組的部分元素時,使用【Repeat count字段】。

僅當檢查浮點數時,采使用【Digits字段】;在此輸入顯示浮點數時要顯示的有效位數,有效位後面的余數作四舍五入處理。【Enabled字段】確定監視項是否當前啟用。

Watch Properties對話框上的其余選項都是顯示選項。每一種數據類型都有一種缺省顯示類型,當用戶選中【Default】時,就使用缺省顯示類型,Default查看選項的默認狀態時“選中”的。選擇其他的查看選項,就以其他方式查看數據。如下圖:

技術分享圖片

要修改一個監視項,可在Watch List中點擊該項,然後在右鍵快捷菜單中選擇【Edit Watch…】菜單項,也可雙擊該監視項,快速打開Watch Properties對話框。

啟用和禁用監視項(Enabling and Disabling Watch Items)

就像使用斷點時一樣,Watch List中每項都可被啟用或禁用。當一個監視項被禁用時,它會變灰,並且它的值顯示為<disabled>。如下圖:

技術分享圖片

要禁用一個監視項,可點擊Watch List中該項的名字,並從Watch List快捷菜單中選擇【Disabled Watch】菜單項;要啟用該監視項,就從快捷菜單中選【Enabled Watch】菜單項。

Note

用戶可能希望禁用當前不使用但以後要使用的監視項。在調試過程中,Watch List中的許多有效監視項會減慢程序執行速度,因為每當一個代碼行執行時,所有Watch List變量都要更新。

向Watch List中添加變量(Adding Variables to the Watch List)

可用多種方法往Watch List中添加監視項。最快速的方法是點擊Code Editor中的變量名,然後從Code Editor的快捷菜單中選擇【Debug | Add Watch at Cursor】或按【Ctrl + F5】鍵,該監視項就會被立即增加到Watch List中。如果需要,用戶可以編輯該監視項,修改其屬性。

技術分享圖片

要增加一個變量到Watch List中而又不想在源文件中找出該變量時,可從主菜單選擇【Run | Add Watch】菜單項;當Watch Properties對話框彈出後,輸入要增加到Watch List中的變量名並點擊OK。

技術分享圖片

Note

雖然可將類實例變量添加到Watch List中,但顯示的值可能無用。如下圖:

技術分享圖片

應該使用Debug Inspector查看類的所有數據成員。

使用Watch List(Using the Watch List)

當碰到斷點時,Watch List顯示其中所有變量的當前值,如果當前沒有打開Watch List窗口,可從主菜單【View | Debug Window | Watches】菜單項打開Watch List窗口。

技術分享圖片

Note

將Watch List窗口泊位到Code Editor窗口的底部,這樣,在調試代碼時,總可以看到它。

在某些情況下,Watch List中變量的後面會顯示一條消息,而不是該變量的值。例如,如果一個變量不在作用域之外,或未找到,Watch List在該變量名後面顯示“Undeclared identifier: ‘X’”;如果程序沒有運行或不停在斷點處,Watch List在所有的監視項後都顯示[process not accessible]。禁用監視項後顯示<disabled>。根據應用程序的當前狀態或某個變量的當前狀態,還可能顯示其他消息。

就像上一章提到過的,用戶在Watch List中偶爾會看到這樣的顯示:variable ‘X‘ inaccessible here due to optimization,這是帶優化功能的編輯器的一個小缺點。如果要檢查易被優化的變量,則必須關閉編譯器的優化功能,即把Project Options對話框中的Compiler頁面上的Optimization選項關閉。

技術分享圖片

未被初始化的變量會顯示隨機值,直到它被初始化。

Note

Watch List可用作一個簡單的十進制/十六進制轉換器。要把一個十六進制數轉換成十進制數,可從主菜單選擇【Run | Add Watch】,在Expression字段輸入十六進制數後點擊OK,輸入的十六進制數和與之等價的十進制數就會顯示在Watch List中;要將一個十進制數轉換成十六進制數,除點擊Hexadecimal單選鈕將顯示類型改為十六進制外,其余操作都與前面相同。由於Expression接受數學表達式,因此還可以把Watch List當做一個十六進制計算器,甚至可以在同一個表達式中同時使用十六進制和十進制值。如下圖:

技術分享圖片

這樣使用Watch List只有一個缺點,應用程序必須停在一個斷點處

在調試應用程序的過程中,Watch List是一個簡單而又關鍵的工作。為了說明Watch List的使用,接下來做一個練習:

1)創建一個應用程序,在其主窗體上放置一個按鈕。將按鈕的Name屬性設置為WatchBtn,Caption屬性改為Watch Test。將主窗體Name屬性改為DebugMain,Caption屬性改為Debug Watch List Test。

2)雙擊按鈕,會在Code Editor中顯示按鈕的OnClick處理事件,按下面的樣子修改其OnClick處理程序:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 procedure TDebugMain.WatchBtnClick(Sender: TObject); var S: string; X, Y: Integer; begin X := Width; S := IntToStr(X); Y := Height; X := X * Y; S := IntToStr(X); X := X div Y; S := IntToStr(X); Width := X; Height := Y; end;

3)保存該工程,將單元命名為DbgMain,工程命名為DebugTest。

4)在OnClick處理程序的begin語句之後的第一行上設置一個斷點,運行該應用程序。

技術分享圖片

5)點擊Watch Test按鈕,調試器會停止在斷點處。當調試器停在斷點處時,IDE和Code Editor會顯示在最頂層。

6)把變量S,X和Y增加到Watch List中(由於代碼優化,變量X和變量Y在開始時是不可訪問的),如下圖:

技術分享圖片

7)安排好Watch List和Code Editor的位置,以便用戶能同時看到兩個窗口(不妨把Watch List泊位到Code Editor的底部)。

8)將輸入焦點切換到Code Editor,並按F8執行下一行代碼,執行完畢後,執行點移到下一行。此時Watch List中變量X顯示一個值。如下圖:

技術分享圖片

9)按F8繼續一行一行執行程序,監視Watch List中變量的結果。

10)當執行點到達OnClick處理程序的最後一行時,點擊工具欄中的Run按鈕繼續運行應用程序。

用戶可反復點擊Watch Test按鈕來體會Watch List是如何工作的,每次還可試驗不同監視設置的效果。

Note

在上面的例子中,OnClick處理程序先獲取主窗體的Width屬性和Height屬性的值,接著執行一些計算,然後再將Width和Height設置成開始時的值。這段程序執行完後,什麽都未發生改變。在該方法末尾給Width和Height屬性賦值是有原因的。

如果在代碼中不真正使用變量X和Y的話,用戶就不能檢查這兩個變量,因為編譯器在優化代碼時會發現這個兩個變量未被使用,從而將它們刪除。在方法的末尾使用這兩個變量就是為了避免編譯器把它們優化掉。

前面提到過這個問題,希望大家對帶優化功能的編譯器的工作過程有個基本了解。這樣,當開始調試應用程序,碰到諸如“Variable ‘Y’ inaccessible here due to optimization”一類的消息時就不會不知所措。

以上代碼均在Delphi7中測試通過,實例代碼下載:WatchList測試程序.rar

Delphi應用程序的調試(三)監視變量