C C測試調(diào)試大全_第1頁
C C測試調(diào)試大全_第2頁
C C測試調(diào)試大全_第3頁
C C測試調(diào)試大全_第4頁
C C測試調(diào)試大全_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、VC調(diào)試方法大全 一、調(diào)試基礎(chǔ)調(diào)試快捷鍵F5:  開始調(diào)試Shift+F5: 停止調(diào)試F10:   調(diào)試到下一句,這里是單步跟蹤  F11:   調(diào)試到下一句,跟進函數(shù)內(nèi)部Shift+F11:  從當前函數(shù)中跳出Ctrl+F10:  調(diào)試到光標所在位置F9:       設(shè)置(取消)斷點Alt+F9:    高級斷點設(shè)置跟蹤調(diào)試1、 盡量使用快捷鍵時行調(diào)試2、 觀察調(diào)

2、試信息3、 高級中斷設(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、 當你移除某個資源時,確保你移除了所有跟這個資源相關(guān)的申明(主要是在resouce.h文中)5、 使用3或者4級的警告級編譯你的代碼,并確保沒有警告,project->setting->c/c+->warni

3、nglevel(中文版是項目->屬性->C/C+->常規(guī)>警告等級)6、 _debug改成NDEBUG進行調(diào)試,project->setting->C/C+->Preprocessordefinitions(中文版是項目->屬性->C/C+->預處理器->預處理定義)(這里是debug和Release編譯的重要不同之一)7、 在Release中調(diào)試源代碼,project->setting->C/C+->debug info選擇programDataBase(中文版是項目->屬性->

4、;C/C+->常規(guī)->調(diào)試信息格式->用于“編輯并繼續(xù)”的程序數(shù)據(jù)庫),project>setting->link選上Generate debug info(中文版是項目->屬性->鏈接器->調(diào)試->生成調(diào)試信息)8、 走讀代碼,特別關(guān)注堆棧和指針二、TRACE宏當選擇了Debug目標,并且afxTraceEnabled變量被置為TRUE時,TRACE宏也就隨之被激活了。但在程序的Release版本中,它們是被完全禁止的。下面是一個典型的TRACE語句:      

5、60;    int nCount =9;       CString strDesc("total");       TRACE("Count =%d,Description =%sn",nCount,strDesc);        可以看到,TRACE語句的工作方式有點像C語言中的printf

6、語句,TRACE宏參數(shù)的個數(shù)是可變的,因此使用起來非常容易。如果查看MFC的源代碼,你根本找不到TRACE宏,而只能看到TRACE0、TRACE1、TRACE2和TRACE3宏,它們的參數(shù)分別為0、1、2、3。個人總結(jié):最近看網(wǎng)絡(luò)編程是碰到了TRACE語句,不知道在哪里輸出,查了一晚上資料也沒找出來,今天終于找到了,方法如下: 1.在MFC中加入TRACE語句2.在TOOLS->MFCTRACER中選擇 “ENABLE TRACING”點擊OK3.進行調(diào)試運行,GO(F5)(特別注意:不是執(zhí)行!以前之所以不能看到TRACE內(nèi)容,是因為不是調(diào)試執(zhí)行,而是!了,切記,切記)  4.

7、然后就會在OUTPUT中的DEBUG窗口中看到TRACE內(nèi)容了,調(diào)試執(zhí)行會自動從BUILD窗口跳到DEBUG窗口,在那里就看到TRACE的內(nèi)容了,_以下是找的TRACE的詳細介紹:       TRACE宏對于VC下程序調(diào)試來說是很有用的東西,有著類似printf的功能;該宏僅僅在程序的DEBUG版本中出現(xiàn),當RELEASE的時候該宏就完全消失了,從而幫助你調(diào)式也在RELEASE的時候減少代碼量。 使用非常簡單,格式如下:TRACE("DDDDDDDDDDD");TRACE("wewe%d&qu

8、ot;,333);同樣還存在TRACE0,TRACE1,TRACE2。分別對應(yīng)0,1,2。個參數(shù)TRACE信息輸出到VC IDE環(huán)境的輸出窗口(該窗口是你編譯項目出錯提示的哪個窗口),但僅限于你在VC中運行你的DEBUG版本的程序。TRACE信息還可以使用DEBUGVIEW來捕獲到。這種情況下,你不能在VC的IDE環(huán)境中運行你的程序,而將BUILD好的DEBUG版本的程序單獨運行,這個時候可以在DEBUGVIEW的窗口看到DEBUGVIE格式的輸出了。VC中TRACE的用法有以下四種:TRACE1 ,就是不帶動態(tài)參數(shù)輸出字符串,  類似C的printf("輸出字符

9、串");  TRACE2: 中的字符串可以帶一個參數(shù)輸出 ,類似C的printf(".%d",變量); TRACE3:可以帶兩個參數(shù)輸出,類似C的printf(".%d.%f",變量1,變量2);TRACE4 可以帶三個參數(shù)輸出,類似C的printf(".%d,%d,%d",變量1,變量2,變量3);TRACE 宏有點象我們以前在C語言中用的Printf函數(shù),使程序在運行過程中輸出一些調(diào)試信息,使我們能了解程序的一些狀態(tài)。但有一點不同的是:TRACE 宏只有在調(diào)試狀態(tài)下才有所輸出,而以前用的Pr

10、intf 函數(shù)在任何情況下都有輸出。和Printf 函數(shù)一樣,TRACE函數(shù)可以接受多個參數(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宏只對Deb

11、ug 版本的工程產(chǎn)生作用,在Release 版本的工程中,TRACE宏將被忽略。三、ASSERT宏如果你設(shè)計了一個函數(shù),該函數(shù)需要一個指向文檔對象的指針做參數(shù),但是你卻錯誤地用一個視圖指針調(diào)用了這個函數(shù)。這個假的地址將導致視數(shù)據(jù)的破壞?,F(xiàn)在,這種類型的問題可以被完全避免,只要在該函數(shù)的開始處實現(xiàn)一個ASSERT測試,用來檢測該指針是否真正指向一個文檔對象。一般來講,編程者在每個函數(shù)的開始處均應(yīng)例行公事地使用assertion。ASSERT宏將會判斷表達式,如果一個表達式為真,執(zhí)行將繼續(xù),否則,程序?qū)@示一條消息并且暫停,你可以選擇忽視這條錯誤并繼續(xù)、終止這個程序或者是跳到Debug器中。下面一

12、例演示了如何使用一個ASSERT宏去驗證一個語句。void foo(char p, int size )                ASSERT( p != 0 ); /確認緩沖區(qū)的指針是有效的     ASSERT( ( size >= 100  ); /確認緩沖區(qū)至少有100個字節(jié)         / D

13、o the foo calculation這些語句不產(chǎn)生任何代碼,除非DEBUG處理器標志被設(shè)置。Visual C只在Debug版本設(shè)置這些標志,而在Release版本不定義這些標志。當DEBUG被定義時,兩個assertions將產(chǎn)生如下代碼:/ASSERT( p!= 0 );      do      if( !(p !=0) && AfxAssertFailedLine(FILE,LINE) )      

14、;   AfxDebugBreak();      while(0);       /ASSERT(size = 100);      do     if(!(size = 100) AfxAssertFailedLine(FILE,LINE)         AfxDebugB

15、reak();while(0);  Dowhile循環(huán)將整個assertion封裝在一個單獨的程序塊中,使得編譯器編譯起來很舒暢。If語句將求取表達式的值并且當結(jié)果為零時調(diào)用AfxAssertFailedLine()函數(shù)。這個函數(shù)將彈出一個對話框,其中提供三個選項“取消、重試或忽略”,當你選取“重試”時,它將返回TRUE。重試將導致對AfxDebugBreak()函數(shù)的調(diào)用,從而激活調(diào)試器。AfxAssertFailedLine()是一個未正式公布的函數(shù),它的功能就是顯示一個消息框。該函數(shù)的源代碼駐留在afxasert.cpp中。函數(shù)中的FILE和LINE語句是處理器標志,它們分別指

16、定了源文件名和當前的行號。 AfxAssertFailedLine()是一個未正式公布的函數(shù),它的功能就是顯示一個消息框。該函數(shù)的源代碼駐留在afxasert.cpp中。函數(shù)中的FILE和LINE語句是處理器標志,它們分別指定了源文件名和當前的行號。 四、VERIFY 宏 因為assertion只能在程序的Debug版本中起作用,在表達式中不可以包含賦值語句、增加語句()或者是減少語句(),因為,這些語句實際改變數(shù)據(jù)。可有時你可能想要驗證一個能動的表達式,使用一個賦值語句。那么就到了用VERIFY宏來替代ASSERT。例如:voidfoo(char p, int

17、size )            char q;              VERIFY(q = p);              ASSERT(size = 100);   &

18、#160;           /Do the foo calculation               /Do the foo calculation         在Debug模式下,ASSERT和VERIFY是一回事,但是在Release模式下,VE

19、RIFY宏仍然測試表達式而assertion卻不起任何作用??梢哉f,在Release模式下,ASSERT語句被刪除了。  請注意,如果你在一個ASSERT語句中錯誤地使用了一個能動的表達式,編譯器將不做任何警告地忽略它。在Release模式下,該表達式就會被無聲息地刪除掉,這將會導致程序的錯誤運行。由于Release版的程序通常不包含Debug信息,這類錯誤將很難被發(fā)現(xiàn)。五、VC高級調(diào)試方法條件及數(shù)據(jù)斷點的設(shè)定(一)位置斷點(LocationBreakpoint)   大家最常用的斷點是普通的位置斷點,在源程序的某一行按F9就設(shè)置了一個位置斷點。但對于很多問題,這

20、種樸素的斷點作用有限。譬如下面這段代碼: void CForDebugDlg:OnOK()        for(int i = 0; i < 1000; i+)    /A                     intk = i * 10 - 2; /B    

21、0;         SendTo(k);          /C              inttmp = DoSome(i); /D              Tr

22、ace0("這里要輸出的內(nèi)容”);/在這里可以輸出一些有用的信息,你也可以輸出I的值,都是可以的              intj = i / tmp;    /E                /其實我們還可以用其他方法調(diào)式也是一樣的,你可以用TRACE0宏來輸出循環(huán)中的每一個結(jié)果,我們也可以在

23、debug中看見輸出的結(jié)果,當出現(xiàn)問題時,輸出的結(jié)果可能就不一樣了,我們可以分析一下debug中的結(jié)果找出問題的所在      執(zhí)行此函數(shù),程序崩潰于E行,發(fā)現(xiàn)此時tmp為0,假設(shè)tmp本不應(yīng)該為0,怎么這個時候為0呢?所以最好能夠跟蹤此次循環(huán)時DoSome函數(shù)是如何運行的,但由于是在循環(huán)體內(nèi),如果在E行設(shè)置斷點,可能需要按F5(GO)許多次。這樣手要不停的按,很痛苦。使用VC6斷點修飾條件就可以輕易解決此問題。步驟如下。   1 Ctrl+B打開斷點設(shè)置框,如下圖: Figure 1設(shè)置高級位置斷點    2 然

24、后選擇D行所在的斷點,然后點擊condition按鈕,在彈出對話框的最下面一個編輯框中輸入一個很大數(shù)目,具體視應(yīng)用而定,這里1000就夠了。   3 按F5重新運行程序,程序中斷。Ctrl+B打開斷點框,發(fā)現(xiàn)此斷點后跟隨一串說明:.487 times remaining。意思是還剩下487次沒有執(zhí)行,那就是說執(zhí)行到513(1000487)次時候出錯的。因此,我們按步驟2所講,更改此斷點的skip次數(shù),將1000改為513。   4 再次重新運行程序,程序執(zhí)行了513次循環(huán),然后自動停在斷點處。這時,我們就可以仔細查看DoSome是如何返回0的。這樣,你就

25、避免了手指的痛苦,節(jié)省了時間。   再看位置斷點其他修飾條件。如Figure 1所示,在“Enter the expression to be evaluated:”下面,可以輸入一些條件,當這些條件滿足時,斷點才啟動。譬如,剛才的程序,我們需要i為100時程序停下來,我們就可以輸入在編輯框中輸入“i=100”。   另外,如果在此編輯框中如果只輸入變量名稱,則變量發(fā)生改變時,斷點才會啟動。這對檢測一個變量何時被修改很方便,特別對一些大程序。   用好位置斷點的修飾條件,可以大大方便解決某些問題。 (二) 數(shù)據(jù)斷點(DataBreak

26、point)  軟件調(diào)試過程中,有時會發(fā)現(xiàn)一些數(shù)據(jù)會莫名其妙的被修改掉(如一些數(shù)組的越界寫導致覆蓋了另外的變量),找出何處代碼導致這塊內(nèi)存被更改是一件棘手的事情(如果沒有調(diào)試器的幫助)。恰當運用數(shù)據(jù)斷點可以快速幫你定位何時何處這個數(shù)據(jù)被修改。譬如下面一段程序: #include "stdafx.h"#include <string.h>int main(int argc, char* argv)       charszName110;    

27、   charszName24;       strcpy(szName1,"shenzhen");                     printf("%sn",szName1);        

28、0; /A        strcpy(szName2,"vckbase");              /B       printf("%sn",szName1);       printf("%sn",szName

29、2);       return0;  這段程序的輸出是         szName1: shenzhen       szName1:ase       szName2:vckbase     首先我給你分析一下為什么會是這樣的結(jié)果呢!首先你在strcpy(szName1,"shenz

30、hen");這個地方F9設(shè)置一個斷點,然后F5運行程序,這是程序會斷到我們設(shè)置的斷點,如下圖  看到了吧,問題出現(xiàn)的原因就在這里,系統(tǒng)給szName2分配的地址是0x0012ff70這里是4個字節(jié),然后呢,在0x0012ff70后面4個字節(jié)處,開始分配szName1這10個字節(jié),也就是在0x0012ff74處開始分配10個字節(jié),       F10單步跟蹤,來到printf("%sn", szName1)這一行,如下圖 szName1分配的空間已經(jīng)附上了值.   F

31、10走到下一個printf("%sn", szName1) 看下圖, 因為szName1 和szName2分配的空間是連續(xù)的,所以給szName2賦值超過所容納的字節(jié)時就開始覆蓋szName1的內(nèi)容了,所以說當我們在輸出結(jié)果的時候就出現(xiàn)我們想不到的結(jié)果了, 那么怎么去調(diào)試呢,下面是具體的方法szName1何時被修改呢?因為沒有明顯的修改szName1代碼。我們可以首先在A行設(shè)置普通斷點,F(xiàn)5運行程序,程序停在A行。然后我們再設(shè)置一個數(shù)據(jù)斷點。如下圖: Figure 2 數(shù)據(jù)斷點   F5繼續(xù)運行,程序停在B行,說明B處代碼修改了szN

32、ame1。B處明明沒有修改szName1呀?但調(diào)試器指明是這一行,一般不會錯,所以還是靜下心來看看程序,哦,你發(fā)現(xiàn)了:szName2只有4個字節(jié),而strcpy了7個字節(jié),所以覆寫了szName1。   數(shù)據(jù)斷點不只是對變量改變有效,還可以設(shè)置變量是否等于某個值。譬如,你可以將Figure 2中紅圈處改為條件”szName20=''''y''''“,那么當szName2第一個字符為y時斷點就會啟動。   可以看出,數(shù)據(jù)斷點相對位置斷點一個很大的區(qū)別是不用明確指明在哪一行代碼設(shè)置斷點。 (三)

33、 其他   1 在call stack窗口中設(shè)置斷點,選擇某個函數(shù),按F9設(shè)置一個斷點。這樣可以從深層次的函數(shù)調(diào)用中迅速返回到需要的函數(shù)。   2 Set Next StateMent命令(debug過程中,右鍵菜單中的命令)  此命令的作用是將程序的指令指針(EIP)指向不同的代碼行。譬如,你正在調(diào)試上面那段代碼,運行在A行,但你不愿意運行B行和C行代碼,這時,你就可以在D行,右鍵,然后“Set Next StateMent”。調(diào)試器就不會執(zhí)行B、C行。只要在同一函數(shù)內(nèi),此指令就可以隨意跳前或跳后執(zhí)行。靈活使用此功能可以大量節(jié)省調(diào)試

34、時間。   3 watch窗口   watch窗口支持豐富的數(shù)據(jù)格式化功能。如輸入0x65,u,則在右欄顯示101。  實時顯示windows API調(diào)用的錯誤:在左欄輸入err,hr。   在watch窗口中調(diào)用函數(shù)。提醒一下,調(diào)用完函數(shù)后馬上在watch窗口中清除它,否則,單步調(diào)試時每一步調(diào)試器都會調(diào)用此函數(shù)。   4 messages斷點不怎么實用?;旧峡梢杂们懊嬷v述的斷點代替。 六、VC調(diào)試環(huán)境設(shè)置為了調(diào)試一個程序,首先必須使程序中包含調(diào)試信息。一般情況下,一個從AppWizard創(chuàng)建的工程中包含的Debug Configuration自動包含調(diào)試信息,但是是不是Debug版本并不是程序包含調(diào)試信息的決定因素,程序設(shè)計者可以在任意的Configuration中增加調(diào)試信息,包括Release版本。為了增加調(diào)試信息,可以按照下述步驟進行:  打開Projectsettings對話框(可以通過快捷鍵ALT+F

溫馨提示

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

評論

0/150

提交評論