概述
除錯是乙個程式設計師最基本的技能,其重要性甚至超過學習一門語言。不會除錯的程式設計師就意味著他即使會一門語言,卻不能編制出任何好的軟體。
這裡我簡要的根據自己的經驗列出除錯中比較常用的技巧,希望對大家有用。
本文約定,在選擇選單時,通過/表示分級選單,例如file/open表示頂級選單file的子選單open。
為了增加除錯資訊,可以按照下述步驟進行:
設定斷點:可以通過下述方法設定乙個斷點。首先把游標移動到需要設定斷點的**行上,然後
去掉斷點:把游標移動到給定斷點所在的行,再次按f9就可以取消斷點。同前面所述,開啟breakpoints對話方塊後,也可以按照介面提示去掉斷點。
條件斷點:可以為斷點設定乙個條件,這樣的斷點稱為條件斷點。對於新加的斷點,可以單擊conditions按鈕,為斷點設定乙個表示式。當這個表示式發生改變時,程式就 被中斷。底下設定包括「觀察陣列或者結構的元素個數」,似乎可以設定乙個指標所指向的記憶體區的大小,但是我設定乙個比較的值但是改動 範圍之外的記憶體區似乎也導致斷點起效。最後乙個設定可以讓程式先執行多少次然後才到達斷點。
資料斷點:資料斷點只能在breakpoints對話方塊中設定。選擇「data」頁,就顯示了設定資料斷點的對話方塊。在編輯框中輸入乙個表示式,當這個 表示式的值發生變化時,資料斷點就到達。一般情況下,這個表示式應該由運算子和全域性變數構成,例如:在編輯框中輸入 g_bflag這個全域性變數的名字,那麼當程式中有g_bflag= !g_bflag時,程式就將停在這個語句處。
訊息斷點:vc也支援對windows訊息進行截獲。他有兩種方式進行截獲:視窗訊息處理函式和特定訊息中斷。
在breakpoints對話方塊中選擇messages頁,就可以設定訊息斷點。如果在上面那個對話方塊中寫入訊息處理函式的名字,那麼 每次訊息被這個函式處理,斷點就到達(我覺得如果採用普通斷點在這個函式中截獲,效果應該一樣)。如果在底下的下拉 列表框選擇乙個訊息,則每次這種訊息到達,程式就中斷。
watch
vc支援檢視變數、表示式和記憶體的值。所有這些觀察都必須是在斷點中斷的情況下進行。
**變數的值最簡單,當斷點到達時,把游標移動到這個變數上,停留一會就可以看到變數的值。
vc提供一種被成為watch的機制來**變數和表示式的值。在斷點狀態下,在變數上單擊右鍵,選擇quick watch, 就彈出乙個對話方塊,顯示這個變數的值。
單擊debug工具條上的watch按鈕,就出現乙個watch檢視(watch1,watch2,watch3,watch4),在該檢視中輸入變數或者表示式,就可以觀察 變數或者表示式的值。注意:這個表示式不能有***,例如++運算子絕對禁止用於這個表示式中,因為這個運算子將修改變數的值,導致 軟體的邏輯被破壞。
memory
由於指標指向的陣列,watch只能顯示第乙個元素的值。為了顯示陣列的後續內容,或者要顯示一片記憶體的內容,可以使用memory功能。在 debug工具條上點memory按鈕,就彈出乙個對話方塊,在其中輸入位址,就可以顯示該位址指向的記憶體的內容。
varibles
debug工具條上的varibles按鈕彈出乙個框,顯示所有當前執行上下文中可見的變數的值。特別是當前指令涉及的變數,以紅色顯示。
暫存器
debug工具條上的reigsters按鈕彈出乙個框,顯示當前的所有暫存器的值。
vc允許被中斷的程式繼續執行、單步執行和執行到指定游標處,分別對應快捷鍵f5、f10/f11和ctrl+f10。各個快捷鍵功能如下:
快捷鍵說明
f5繼續執行
f10單步,如果涉及到子函式,不進入子函式內部
f11單步,如果涉及到子函式,進入子函式內部
ctrl+f10
執行到當前游標處。
呼叫堆疊反映了當前斷點處函式是被那些函式按照什麼順序呼叫的。單擊debug工具條上的call stack就顯示call stack對話方塊。在callstack對話方塊中顯示了乙個呼叫系列,最上面的是當前函式,往下依次是呼叫函式的上級函式。單擊這些函式名可以跳到對應的函式中去。
系統提供一系列特殊的函式或者巨集來處理debug版本相關的資訊,如下:
巨集名/函式名說明
trace
使用方法和printf完全一致,他在output框中輸出除錯資訊
assert
它接收乙個表示式,如果這個表示式為true,則無動作,否則中斷當前程式執行。對於系統中出現這個巨集 導致的中斷,應該認為你的函式呼叫未能滿足系統的呼叫此函式的前提條件。例如,對於乙個還沒有建立的視窗呼叫setwindowtext等。
verify
和assert功能類似,所不同的是,在release版本中,assert不計算輸入的表示式的值,而verify計算表示式的值。
乙個好的程式設計師不應該把所有的判斷交給編譯器和偵錯程式,應該在程式中自己加以程式保護和錯誤定位,具體措施包括:
另外:vc中要編制程式不應該一開始就寫cpp/h檔案,而應該首先建立乙個合適的工程。因為只有這樣,vc才能選擇合適的編譯、連線 選項。對於加入到工程中的cpp檔案,應該檢查是否在第一行顯式的包含stdafx.h標頭檔案,這是microsoft visual studio為了加快編譯 速度而設定的預編譯標頭檔案。在這個#include "stdafx.h"行前面的所有**將被忽略,所以其他標頭檔案應該在這一行後面被包含。
對於.c檔案,由於不能包含stdafx.h,因此可以通過project settings把它的預編譯頭設定為「不使用」,方法是:
除錯方法和技巧
便於除錯的**風格:
不用全域性變數
所有變數都要初始化,成員變數在建構函式中初始化
盡量使用const
詳盡的注釋
vc++編譯選項:
總是使用/w4警告級別
在除錯版本裡總是使用/gz編譯選項,用來發現在release版本中才有的錯誤
沒有警告的編譯:保證在編譯後沒有任何警告,但是在消除警告前要進行仔細檢查
除錯方法:
1、使用 assert(原則:盡量簡單)
assert只在debug下生效,release下不會被編譯。
例子:
char* strcpy(char* dest,char* source)2、防禦性的程式設計return returnstring;
}
例子:
char* strcpy(char* dest,char* source)3、使用traceif(dest == 0)
char* returnstring = dest;
while((*dest++ = *source++)!= 『\0』)
return returnstring;
}
以下的例子只能在debug中顯示,
例子:a)、trace
cstring cstest = 「test」;b)、atltracetrace(「cstring is %s\n」,cstest);
c)、afxdump
ctime time = ctime::getcurrenttime();4、用getlasterror來檢測返回值,通過得到錯誤**來分析錯誤原因#ifdef _debug
afxdump << time << 「\n」;
#endif
5、把錯誤資訊記錄到檔案中
異常處理
程式設計時一定要考慮到異常如何處理,當錯誤發生後,不應簡單的報告錯誤並退出程式,應當盡可能的想辦法恢復到出錯前的狀態或者讓程式從頭開始執行,並且對於某些錯誤,應該能夠容錯,即允許錯誤的存在,但是程式還是能夠正常完成任務。
除錯技巧
1、在函式返回的時候程式崩潰的原因
a)、寫自動變數越界
b)、函式原型不匹配
2、mfc
a)、使用錯誤的函式原型處理使用者定義訊息
正確的函式原型為:
afx_msg lresult onmymessage(wparam wparam,lparam lparam);3、謹慎使用terminatethread:使用terminatethread會造成資源洩漏,不到萬不得已,不要使用。
4、使用_beginthreadex,不要使用create thread來常見執行緒。
VC除錯入門
概述 除錯是乙個程式設計師最基本的技能,其重要性甚至超過學習一門語言。不會除錯的程式設計師就意味著他即使會一門語言,卻不能編制出任何好的軟體。這裡我簡要的根據自己的經驗列出除錯中比較常用的技巧,希望對大家有用。本文約定,在選擇選單時,通過 表示分級選單,例如file open表示頂級選單file的子...
VC 除錯入門
vc除錯入門 設定斷點 可以通過下述方法設定乙個斷點。首先把游標移動到需要設定斷點的 行上,然後 去掉斷點 把游標移動到給定斷點所在的行,再次按f9就可以取消斷點。同前面所述,開啟breakpoints對話方塊後,也可以按照介面提示去掉斷點。條件斷點 可以為斷點設定乙個條件,這樣的斷點稱為條件斷點。...
VC除錯技術
函式的返回值儲存在eax中 this 儲存在ecx中 thiscall,fastcal,cdcall stdcall不一定 有時存在eax中 this指標 也就是乙個物件的初始位址 char p hello world watch 監視視窗 p,100x00416800 hello world ch...