VC調(diào)試方法大全.doc_第1頁
VC調(diào)試方法大全.doc_第2頁
VC調(diào)試方法大全.doc_第3頁
VC調(diào)試方法大全.doc_第4頁
VC調(diào)試方法大全.doc_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

VC調(diào)試方法大全一、調(diào)試基礎(chǔ)調(diào)試快捷鍵F5: 開始調(diào)試Shift+F5: 停止調(diào)試F10: 調(diào)試到下一句,這里是單步跟蹤 F11: 調(diào)試到下一句,跟進(jìn)函數(shù)內(nèi)部Shift+F11:從當(dāng)前函數(shù)中跳出Ctrl+F10:調(diào)試到光標(biāo)所在位置F9: 設(shè)置(取消)斷點(diǎn)Alt+F9:高級(jí)斷點(diǎn)設(shè)置跟蹤調(diào)試1、盡量使用快捷鍵時(shí)行調(diào)試2、觀察調(diào)試信息3、高級(jí)中斷設(shè)置異常調(diào)試重試取消調(diào)試函數(shù)堆棧,用variables或者call stack 窗口Release調(diào)試1、經(jīng)常測試你的Debug和Release版本2、不要移除調(diào)試代碼,如用ASSERT, TRACE等。3、初始化變量,特別是全局變量,malloc的內(nèi)存,new的內(nèi)存4、當(dāng)你移除某個(gè)資源時(shí),確保你移除了所有跟這個(gè)資源相關(guān)的申明(主要是在resouce.h文中)5、使用3或者4級(jí)的警告級(jí)編譯你的代碼,并確保沒有警告,project-setting-c/c+-warninglevel(中文版是項(xiàng)目-屬性-C/C+-常規(guī)警告等級(jí))6、_debug改成NDEBUG進(jìn)行調(diào)試,project-setting-C/C+-Preprocessordefinitions(中文版是項(xiàng)目-屬性-C/C+-預(yù)處理器-預(yù)處理定義)(這里是debug和Release編譯的重要不同之一)7、在Release中調(diào)試源代碼,project-setting-C/C+-debug info選擇programDataBase(中文版是項(xiàng)目-屬性-C/C+-常規(guī)-調(diào)試信息格式-用于“編輯并繼續(xù)”的程序數(shù)據(jù)庫),projectsetting-link選上Generate debug info(中文版是項(xiàng)目-屬性-鏈接器-調(diào)試-生成調(diào)試信息)8、走讀代碼,特別關(guān)注堆棧和指針二、TRACE宏當(dāng)選擇了Debug目標(biāo),并且afxTraceEnabled變量被置為TRUE時(shí),TRACE宏也就隨之被激活了。但在程序的Release版本中,它們是被完全禁止的。下面是一個(gè)典型的TRACE語句:int nCount =9;CString strDesc(total);TRACE(Count =%d,Description =%sn,nCount,strDesc);可以看到,TRACE語句的工作方式有點(diǎn)像C語言中的printf語句,TRACE宏參數(shù)的個(gè)數(shù)是可變的,因此使用起來非常容易。如果查看MFC的源代碼,你根本找不到TRACE宏,而只能看到TRACE0、TRACE1、TRACE2和TRACE3宏,它們的參數(shù)分別為0、1、2、3。個(gè)人總結(jié):最近看網(wǎng)絡(luò)編程是碰到了TRACE語句,不知道在哪里輸出,查了一晚上資料也沒找出來,今天終于找到了,方法如下: 1.在MFC中加入TRACE語句2.在TOOLS-MFCTRACER中選擇 “ENABLE TRACING”點(diǎn)擊OK3.進(jìn)行調(diào)試運(yùn)行,GO(F5)(特別注意:不是執(zhí)行!以前之所以不能看到TRACE內(nèi)容,是因?yàn)椴皇钦{(diào)試執(zhí)行,而是!了,切記,切記) 4.然后就會(huì)在OUTPUT中的DEBUG窗口中看到TRACE內(nèi)容了,調(diào)試執(zhí)行會(huì)自動(dòng)從BUILD窗口跳到DEBUG窗口,在那里就看到TRACE的內(nèi)容了,_以下是找的TRACE的詳細(xì)介紹:TRACE宏對(duì)于VC下程序調(diào)試來說是很有用的東西,有著類似printf的功能;該宏僅僅在程序的DEBUG版本中出現(xiàn),當(dāng)RELEASE的時(shí)候該宏就完全消失了,從而幫助你調(diào)式也在RELEASE的時(shí)候減少代碼量。 使用非常簡單,格式如下:TRACE(DDDDDDDDDDD);TRACE(wewe%d,333);同樣還存在TRACE0,TRACE1,TRACE2。分別對(duì)應(yīng)0,1,2。個(gè)參數(shù)TRACE信息輸出到VC IDE環(huán)境的輸出窗口(該窗口是你編譯項(xiàng)目出錯(cuò)提示的哪個(gè)窗口),但僅限于你在VC中運(yùn)行你的DEBUG版本的程序。TRACE信息還可以使用DEBUGVIEW來捕獲到。這種情況下,你不能在VC的IDE環(huán)境中運(yùn)行你的程序,而將BUILD好的DEBUG版本的程序單獨(dú)運(yùn)行,這個(gè)時(shí)候可以在DEBUGVIEW的窗口看到DEBUGVIE格式的輸出了。VC中TRACE的用法有以下四種:TRACE1 ,就是不帶動(dòng)態(tài)參數(shù)輸出字符串,類似C的printf(輸出字符串); TRACE2:中的字符串可以帶一個(gè)參數(shù)輸出,類似C的printf(.%d,變量); TRACE3:可以帶兩個(gè)參數(shù)輸出,類似C的printf(.%d.%f,變量1,變量2);TRACE4 可以帶三個(gè)參數(shù)輸出,類似C的printf(.%d,%d,%d,變量1,變量2,變量3);TRACE 宏有點(diǎn)象我們以前在C語言中用的Printf函數(shù),使程序在運(yùn)行過程中輸出一些調(diào)試信息,使我們能了解程序的一些狀態(tài)。但有一點(diǎn)不同的是:TRACE 宏只有在調(diào)試狀態(tài)下才有所輸出,而以前用的Printf 函數(shù)在任何情況下都有輸出。和Printf 函數(shù)一樣,TRACE函數(shù)可以接受多個(gè)參數(shù)如:int x = 1;int y = 16;float z = 32.0;TRACE( This is a TRACE statementn );TRACE( The value of x is %dn, x );TRACE( x = %d and y = %dn, x, y );TRACE( x = %d and y = %x and z = %fn, x, y, z );要注意的是TRACE宏只對(duì)Debug 版本的工程產(chǎn)生作用,在Release 版本的工程中,TRACE宏將被忽略。三、ASSERT宏如果你設(shè)計(jì)了一個(gè)函數(shù),該函數(shù)需要一個(gè)指向文檔對(duì)象的指針做參數(shù),但是你卻錯(cuò)誤地用一個(gè)視圖指針調(diào)用了這個(gè)函數(shù)。這個(gè)假的地址將導(dǎo)致視數(shù)據(jù)的破壞。現(xiàn)在,這種類型的問題可以被完全避免,只要在該函數(shù)的開始處實(shí)現(xiàn)一個(gè)ASSERT測試,用來檢測該指針是否真正指向一個(gè)文檔對(duì)象。一般來講,編程者在每個(gè)函數(shù)的開始處均應(yīng)例行公事地使用assertion。ASSERT宏將會(huì)判斷表達(dá)式,如果一個(gè)表達(dá)式為真,執(zhí)行將繼續(xù),否則,程序?qū)@示一條消息并且暫停,你可以選擇忽視這條錯(cuò)誤并繼續(xù)、終止這個(gè)程序或者是跳到Debug器中。下面一例演示了如何使用一個(gè)ASSERT宏去驗(yàn)證一個(gè)語句。void foo(char p, int size ) ASSERT( p != 0); /確認(rèn)緩沖區(qū)的指針是有效的 ASSERT( ( size = 100 ); /確認(rèn)緩沖區(qū)至少有100個(gè)字節(jié) / Do the foo calculation這些語句不產(chǎn)生任何代碼,除非DEBUG處理器標(biāo)志被設(shè)置。Visual C只在Debug版本設(shè)置這些標(biāo)志,而在Release版本不定義這些標(biāo)志。當(dāng)DEBUG被定義時(shí),兩個(gè)assertions將產(chǎn)生如下代碼:/ASSERT( p!= 0 );do if( !(p !=0)& AfxAssertFailedLine(FILE,LINE) ) AfxDebugBreak();while(0); /ASSERT(size = 100);do if(!(size = 100) AfxAssertFailedLine(FILE,LINE) AfxDebugBreak();while(0); Dowhile循環(huán)將整個(gè)assertion封裝在一個(gè)單獨(dú)的程序塊中,使得編譯器編譯起來很舒暢。If語句將求取表達(dá)式的值并且當(dāng)結(jié)果為零時(shí)調(diào)用AfxAssertFailedLine()函數(shù)。這個(gè)函數(shù)將彈出一個(gè)對(duì)話框,其中提供三個(gè)選項(xiàng)“取消、重試或忽略”,當(dāng)你選取“重試”時(shí),它將返回TRUE。重試將導(dǎo)致對(duì)AfxDebugBreak()函數(shù)的調(diào)用,從而激活調(diào)試器。AfxAssertFailedLine()是一個(gè)未正式公布的函數(shù),它的功能就是顯示一個(gè)消息框。該函數(shù)的源代碼駐留在afxasert.cpp中。函數(shù)中的FILE和LINE語句是處理器標(biāo)志,它們分別指定了源文件名和當(dāng)前的行號(hào)。AfxAssertFailedLine()是一個(gè)未正式公布的函數(shù),它的功能就是顯示一個(gè)消息框。該函數(shù)的源代碼駐留在afxasert.cpp中。函數(shù)中的FILE和LINE語句是處理器標(biāo)志,它們分別指定了源文件名和當(dāng)前的行號(hào)。四、VERIFY 宏因?yàn)閍ssertion只能在程序的Debug版本中起作用,在表達(dá)式中不可以包含賦值語句、增加語句()或者是減少語句(),因?yàn)?,這些語句實(shí)際改變數(shù)據(jù)??捎袝r(shí)你可能想要驗(yàn)證一個(gè)能動(dòng)的表達(dá)式,使用一個(gè)賦值語句。那么就到了用VERIFY宏來替代ASSERT。例如:voidfoo(char p, int size ) char q;VERIFY(q = p);ASSERT(size = 100);/Do the foo calculation/Do the foo calculation 在Debug模式下,ASSERT和VERIFY是一回事,但是在Release模式下,VERIFY宏仍然測試表達(dá)式而assertion卻不起任何作用。可以說,在Release模式下,ASSERT語句被刪除了。 請(qǐng)注意,如果你在一個(gè)ASSERT語句中錯(cuò)誤地使用了一個(gè)能動(dòng)的表達(dá)式,編譯器將不做任何警告地忽略它。在Release模式下,該表達(dá)式就會(huì)被無聲息地刪除掉,這將會(huì)導(dǎo)致程序的錯(cuò)誤運(yùn)行。由于Release版的程序通常不包含Debug信息,這類錯(cuò)誤將很難被發(fā)現(xiàn)。五、VC高級(jí)調(diào)試方法條件及數(shù)據(jù)斷點(diǎn)的設(shè)定(一)位置斷點(diǎn)(LocationBreakpoint) 大家最常用的斷點(diǎn)是普通的位置斷點(diǎn),在源程序的某一行按F9就設(shè)置了一個(gè)位置斷點(diǎn)。但對(duì)于很多問題,這種樸素的斷點(diǎn)作用有限。譬如下面這段代碼: void CForDebugDlg:OnOK() for(int i = 0; i 1000; i+) /A intk = i * 10 - 2; /B SendTo(k); /C inttmp = DoSome(i); /D Trace0(這里要輸出的內(nèi)容”);/在這里可以輸出一些有用的信息,你也可以輸出I的值,都是可以的 intj = i / tmp; /E /其實(shí)我們還可以用其他方法調(diào)式也是一樣的,你可以用TRACE0宏來輸出循環(huán)中的每一個(gè)結(jié)果,我們也可以在debug中看見輸出的結(jié)果,當(dāng)出現(xiàn)問題時(shí),輸出的結(jié)果可能就不一樣了,我們可以分析一下debug中的結(jié)果找出問題的所在 執(zhí)行此函數(shù),程序崩潰于E行,發(fā)現(xiàn)此時(shí)tmp為0,假設(shè)tmp本不應(yīng)該為0,怎么這個(gè)時(shí)候?yàn)?呢?所以最好能夠跟蹤此次循環(huán)時(shí)DoSome函數(shù)是如何運(yùn)行的,但由于是在循環(huán)體內(nèi),如果在E行設(shè)置斷點(diǎn),可能需要按F5(GO)許多次。這樣手要不停的按,很痛苦。使用VC6斷點(diǎn)修飾條件就可以輕易解決此問題。步驟如下。 1 Ctrl+B打開斷點(diǎn)設(shè)置框,如下圖: Figure 1設(shè)置高級(jí)位置斷點(diǎn) 2 然后選擇D行所在的斷點(diǎn),然后點(diǎn)擊condition按鈕,在彈出對(duì)話框的最下面一個(gè)編輯框中輸入一個(gè)很大數(shù)目,具體視應(yīng)用而定,這里1000就夠了。 3 按F5重新運(yùn)行程序,程序中斷。Ctrl+B打開斷點(diǎn)框,發(fā)現(xiàn)此斷點(diǎn)后跟隨一串說明:.487 times remaining。意思是還剩下487次沒有執(zhí)行,那就是說執(zhí)行到513(1000487)次時(shí)候出錯(cuò)的。因此,我們按步驟2所講,更改此斷點(diǎn)的skip次數(shù),將1000改為513。 4 再次重新運(yùn)行程序,程序執(zhí)行了513次循環(huán),然后自動(dòng)停在斷點(diǎn)處。這時(shí),我們就可以仔細(xì)查看DoSome是如何返回0的。這樣,你就避免了手指的痛苦,節(jié)省了時(shí)間。 再看位置斷點(diǎn)其他修飾條件。如Figure 1所示,在“Enter the expression to be evaluated:”下面,可以輸入一些條件,當(dāng)這些條件滿足時(shí),斷點(diǎn)才啟動(dòng)。譬如,剛才的程序,我們需要i為100時(shí)程序停下來,我們就可以輸入在編輯框中輸入“i=100”。 另外,如果在此編輯框中如果只輸入變量名稱,則變量發(fā)生改變時(shí),斷點(diǎn)才會(huì)啟動(dòng)。這對(duì)檢測一個(gè)變量何時(shí)被修改很方便,特別對(duì)一些大程序。 用好位置斷點(diǎn)的修飾條件,可以大大方便解決某些問題。 (二) 數(shù)據(jù)斷點(diǎn)(DataBreakpoint) 軟件調(diào)試過程中,有時(shí)會(huì)發(fā)現(xiàn)一些數(shù)據(jù)會(huì)莫名其妙的被修改掉(如一些數(shù)組的越界寫導(dǎo)致覆蓋了另外的變量),找出何處代碼導(dǎo)致這塊內(nèi)存被更改是一件棘手的事情(如果沒有調(diào)試器的幫助)。恰當(dāng)運(yùn)用數(shù)據(jù)斷點(diǎn)可以快速幫你定位何時(shí)何處這個(gè)數(shù)據(jù)被修改。譬如下面一段程序: #include stdafx.h#include int main(int argc, char* argv) charszName110; charszName24; strcpy(szName1,shenzhen); printf(%sn,szName1); /A strcpy(szName2,vckbase); /B printf(%sn,szName1); printf(%sn,szName2); return0;這段程序的輸出是 szName1: shenzhen szName1:ase szName2:vckbase 首先我給你分析一下為什么會(huì)是這樣的結(jié)果呢!首先你在strcpy(szName1,shenzhen);這個(gè)地方F9設(shè)置一個(gè)斷點(diǎn),然后F5運(yùn)行程序,這是程序會(huì)斷到我們?cè)O(shè)置的斷點(diǎn),如下圖 看到了吧,問題出現(xiàn)的原因就在這里,系統(tǒng)給szName2分配的地址是0x0012ff70這里是4個(gè)字節(jié),然后呢,在0x0012ff70后面4個(gè)字節(jié)處,開始分配szName1這10個(gè)字節(jié),也就是在0x0012ff74處開始分配10個(gè)字節(jié), F10單步跟蹤,來到printf(%sn, szName1)這一行,如下圖szName1分配的空間已經(jīng)附上了值. F10走到下一個(gè)printf(%sn, szName1) 看下圖,因?yàn)閟zName1 和szName2分配的空間是連續(xù)的,所以給szName2賦值超過所容納的字節(jié)時(shí)就開始覆蓋szName1的內(nèi)容了,所以說當(dāng)我們?cè)谳敵鼋Y(jié)果的時(shí)候就出現(xiàn)我們想不到的結(jié)果了,那么怎么去調(diào)試呢,下面是具體的方法szName1何時(shí)被修改呢?因?yàn)闆]有明顯的修改szName1代碼。我們可以首先在A行設(shè)置普通斷點(diǎn),F(xiàn)5運(yùn)行程序,程序停在A行。然后我們?cè)僭O(shè)置一個(gè)數(shù)據(jù)斷點(diǎn)。如下圖: Figure 2 數(shù)據(jù)斷點(diǎn) F5繼續(xù)運(yùn)行,程序停在B行,說明B處代碼修改了szName1。B處明明沒有修改szName1呀?但調(diào)試器指明是這一行,一般不會(huì)錯(cuò),所以還是靜下心來看看程序,哦,你發(fā)現(xiàn)了:szName2只有4個(gè)字節(jié),而strcpy了7個(gè)字節(jié),所以覆寫了szName1。 數(shù)據(jù)斷點(diǎn)不只是對(duì)變量改變有效,還可以設(shè)置變量是否等于某個(gè)值。譬如,你可以將Figure 2中紅圈處改為條件”szName20=y“,那么當(dāng)szName2第一個(gè)字符為y時(shí)斷點(diǎn)就會(huì)啟動(dòng)。 可以看出,數(shù)據(jù)斷點(diǎn)相對(duì)位置斷點(diǎn)一個(gè)很大的區(qū)別是不用明確指明在哪一行代碼設(shè)置斷點(diǎn)。 (三) 其他 1 在call stack窗口中設(shè)置斷點(diǎn),選擇某個(gè)函數(shù),按F9設(shè)置一個(gè)斷點(diǎn)。這樣可以從深層次的函數(shù)調(diào)用中迅速返回到需要的函數(shù)。 2 Set Next StateMent命令(debug過程中,右鍵菜單中的命令) 此命令的作用是將程序的指令指針(EIP)指向不同的代碼行。譬如,你正在調(diào)試上面那段代碼,運(yùn)行在A行,但你不愿意運(yùn)行B行和C行代碼,這時(shí),你就可以在D行,右鍵,然后“Set Next StateMent”。調(diào)試器就不會(huì)執(zhí)行B、C行。只要在同一函數(shù)內(nèi),此指令就可以隨意跳前或跳后執(zhí)行。靈活使用此功能可以大量節(jié)省調(diào)試時(shí)間。 3 watch窗口 watch窗口支持豐富的數(shù)據(jù)格式化功能。如輸入0x65,u,則在右欄顯示101。 實(shí)時(shí)顯示windows API調(diào)用的錯(cuò)誤:在左欄輸入err,hr。 在watch窗口中調(diào)用函數(shù)。提醒一下,調(diào)用完函數(shù)后馬上在watch窗口中清除它,否則,單步調(diào)試時(shí)每一步調(diào)試器都會(huì)調(diào)用此函數(shù)。 4 messages斷點(diǎn)不怎么實(shí)用?;旧峡梢杂们懊嬷v述的斷點(diǎn)代替。 六。VC調(diào)試環(huán)境設(shè)置為了調(diào)試一個(gè)程序,首先必須使程序中包含調(diào)試信息。一般情況下,一個(gè)從AppWi

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論