MATLAB 程式設計入門篇 程式除錯 張智星 (Roger Jang) jang@mirlab.org http://mirlab.org/~jang 清大資工系 多媒體檢索實驗室
17-1 簡介 MATLAB 的除錯器(Debugger)功能包含: 一般程式語言的錯誤分類 查詢每一個函數的工作空間(Workspace) 顯示函數呼叫過程中的的堆疊(Function Call Stack) 一列一列地執行 M 檔案(Step-by-step Execution) 一般程式語言的錯誤分類 語法錯誤 邏輯錯誤
17-2 一般除錯技巧(1/2) 一般偵測邏輯錯誤的方法: 去除運算式最尾端的分號,運算式執行的結果會印在 MATLAB 指令視窗中。 在程式中加入 keyboard 指令,可使程式執行至此處即暫停,並顯示“k >>”的提示號(k 代表 keyboard),以便查看或改變工作空間的任何變數,若要繼續執行程式,可在 MATLAB 指令視窗下輸入“return”並按下 Enter 鍵。
17-2 一般除錯技巧(2/2) 使用判斷式及 fprintf 指令印出變數的值。 在除錯一個單獨函數時,可在其第一列的函數宣告列加上 %,並定義輸入引數的值,此時我們就可以直接以腳本(Scripts)的方式來執行此 M 檔案,並保留所有變數於 MATLAB 工作空間之中。 使用 MATLAB 的除錯器。
17-3以命令列為主的除錯程式(1/2) 語 法 功 能 dbstop at line# in filename 語 法 功 能 dbstop at line# in filename 設定中斷點(Break Points) (line# 代表行號,filename 代表檔案名稱) dbclear at line# in filename 清除中斷點 (line#代表行號,filename 代表檔案名稱) dbstop if warning dbstop if error dbstop if naninf dbstop if infnan 若遇到「警告」(Warning)、「錯誤」(Error)、或「非數值/無窮大」(NaN/Inf),則暫停程式執行
17-3以命令列為主的除錯程式(2/2) dbcont 從暫停狀態繼續執行 dbstackdbstatus filename 列出某檔案的所有中斷點 (filename 代表檔案名稱) dbstep n 執行 n 列指令 dbtype filename 列出檔案內容(包含每列編號) dbdown 向下進入局部的工作空間 dbup 向上進入呼叫端的工作空間 dbquit 離開除錯模式
dbstop 的一般格式及相關說明 可以利用dbstop來指定程式碼的中斷點 指 令 格 式 說 明 指 令 格 式 說 明 dbstop in filename at line# 停止執行於某檔案的某行 dbstop in filename at subfunction 停止執行於某檔案的次函數 dbstop in filename 停止執行於某檔案 dbstop if error 若出現錯誤,則暫停程式執行,並停留在發生錯誤的工作空間 dbstop if warning 若出現警告,則暫停程式執行,並停留在發生警告的工作空間 dbstop if naninf dbstop if infnan 若出現 nan 或 inf,則暫停程式執行,並停留在發生 nan 或 inf的工作空間
離開除錯模式後的動作 進入除錯模式後,可檢查任何變數的值,也可以執行其他任何指令或手稿(script)。 檢查完畢後,可能採取的動作有: 指 令 格 式 說 明 dbcont 繼續執行程式 dbstep n 執行 n 列程式碼 dbtype filename 列出程式碼 dbdown 向下切換至另一個工作空間 dbup 向上切換至另一個工作空間 dbstack 列出函數呼叫過程中的堆疊 dbquit 跳出除錯模式
dbstep 的格式及說明 dbstep可以一次執行一列或多列程式碼,或是進入或跳出一個指令的內部程式碼 。 指 令 格 式 說 明 指 令 格 式 說 明 dbstep 執行下一列程式碼 dbstep n 執行下 n 列程式碼 dbstep in 進入下一列指令的程式碼 dbstep out 跳出目前指令的程式碼
dbclear及dbstatus 的用法 dbclear 用於取消中斷點,用法與dbstop的格式同,只需將dbstop改成dbclear。若要清除所有的中斷點,可用 dbclear all。 dbstatus 可列出所有的中斷點。 指 令 格 式 說 明 dbstatus 列出所有中斷點 dbstatus filename 列出在一檔案中的中斷點 s = dbstatus(…) 將中斷點的資訊傳回變數 s
實例:計算一向量的倒數和 範例: recipsum.m 此函數包含一錯誤,執行時即會出現: >> type recipsum function out = recipsum(x) recip = reciproc(x); out = sum(recip); function output = reciproc(input) output = 1./x; >> recipsum([1 2 3]) ??? Input argument 'x' is undefined. Error in ==> D:\matlabBook\MATLAB程式設計:基本篇\17-程式除錯\recipsum.m On line 3 ==> recip = reciproc(x);
使用dbstop及dbstatus 讓MATLAB 停留在產生錯誤訊息的函數: >> dbstop if error 確認所建的中斷條件: >> dbstatus Stop if error. 再呼叫原函數,會停在錯誤發生的程式碼:
使用dbstack及dbtype 此時可在指令視窗使用 dbstack 來顯示 MATLAB 所在的函數: k>> dbstack > In recipsum>reciproc at 7 In recipsum at 3 k>> dbtype 1 function out = recipsum(x) 2 3 recip = reciproc(x); 4 out = sum(recip); 5 6 function output = reciproc(input) 7 output = 1./x;
使用dbquit、dbup及dbdown 在除錯器中將x改成input,則正確答案為: 當程式暫停執行於一個函數時,可以使用 dbup 及 dbdown 來跳到不同的工作空間,以便檢視各變數。 k>> dbquit % 離開除錯模式 >> recipsum1([1 2 3]) ans = 1.8333
設立中斷條件 上述範例修正後的檔案為recipsum1.m,執行時還是可能會有問題 => Divide by zero. 另設一個中斷條件來檢查錯誤所在,再呼叫函數: >> recipsum1([2 0 2]) ans = Inf >> dbstop if naninf >> recipsum1([2 0 2]) NaN/Inf breakpoint hit for recipsum1 on line 4. 4 out = sum(recip); K>>
除錯後的最終結果 假設在輸入為 0 時,其倒數不計,則程式碼可修正如下,recipsum2.m: 正確答案為: k>> dbquit % 離開除錯模式 >> type recipsum2 function out = recipsum(x) recip = reciproc(x); out = sum(recip); function output = reciproc(input) input(find(input==0)) = []; % Eliminate "0" elements output = 1./input; >> recipsum2([2 0 2]) ans = 1
17-4以圖形介面進行程式除錯 進行除錯,可由指令列下達 edit 或 open 指令,例如: >> edit recipsum1 可開啟 MATLAB 除錯器(也是編輯器)
除錯指令與圖示 圖 示 MATLAB 對應指令 說 明 dbstop/dbclear 設立或移除中斷點 dbclear all 圖 示 MATLAB 對應指令 說 明 dbstop/dbclear 設立或移除中斷點 dbclear all 移除所有中斷點 dbstep 執行下一列程式碼 dbstep in 進入某函數程式碼 dbstep out 退出某函數程式碼 dbcont 繼續執行程式碼 dbquit 跳出除錯模式 dbtype 列出程式碼
設立中斷點(1) 欲設立中斷點於 reciproc 函數的第一列,可利用滑鼠將游標置於該列並點取 圖示。(紅點,代表中斷點 )
設立中斷點(2) 若執行此函數,即可停於該中斷點: >> recipsum1([1 2 3]) (綠色箭號顯示現在所在的位置 )
檢視變數或運算式 中斷後可在指令列檢視各個變數的值,或選取工具列上的 stack 下接式選單,以跳至不同的工作空間。 檢視變數或運算式有三 : 將游標移到變數附近 在指令列輸入變數或運算式。 選取變數或運算式後,利用滑鼠右鍵點取,並選擇“Evaluate Selection”。
逐步執行 若按下 圖示(或在指令列輸入 dbstep),則綠色箭號變成向下,代表即將離開此次函數。
不同版本的MATLAB圖示對應關係 第六/七版 圖示 第五版 MATLAB 對應指令 說 明 dbstop/dbclear 設立或移除中斷點 說 明 dbstop/dbclear 設立或移除中斷點 dbclear all 移除所有中斷點 dbstep 執行下一列程式碼 dbstep in 進入某函數程式碼 無 dbstep out 退出某函數程式碼 dbcont 繼續執行程式碼 dbquit 跳出除錯模式 dbtype 列出程式碼