VC調試方法

一、調試基礎


調試快捷鍵


F5:  開始調試


Shift+F5: 停止調試


F10:   調試到下一句,這裏是單步跟蹤 


F11:   調試到下一句,跟進函數內部


Shift+F11:  從當前函數中跳出


Ctrl+F10:  調試到光標所在位置


F9:       設置(取消)斷點


Alt+F9:    高級斷點設置


跟蹤調試


1、 儘量使用快捷鍵時行調試


2、 觀察調試信息


3、 高級中斷設置


異常調試


重試->取消->調試


函數堆棧,用variables或者call stack 窗口


Release調試


1、 經常測試你的Debug和Release版本


2、 不要移除調試代碼,如用ASSERT, TRACE等。


3、 初始化變量,特別是全局變量,malloc的內存,new的內存


4、 當你移除某個資源時,確保你移除了所有跟這個資源相關的申明(主要是在resouce.h文中)


5、 使用3或者4級的警告級編譯你的代碼,並確保沒有警告,project->setting->c/c++->warninglevel(中文版是項目->屬性->C/C++->常規->警告等級)


6、 _debug改成NDEBUG進行調試,project->setting->C/C++->Preprocessordefinitions(中文版是項目->屬性->C/C++->預處理器->預處理定義)(這裏是debug和Release編譯的重要不同之一)


7、 在Release中調試源代碼,project->setting->C/C++->debug info選擇programDataBase(中文版是項目->屬性->C/C++->常規->調試信息格式->用於“編輯並繼續”的程序數據庫),project->setting->link選上Generate debug info(中文版是項目->屬性->鏈接器->調試->生成調試信息)


8、 走讀代碼,特別關注堆棧和指針


二、TRACE宏


當選擇了Debug目標,並且afxTraceEnabled變量被置爲TRUE時,TRACE宏也就隨之被激活了。但在程序的Release版本中,它們是被完全禁止的。下面是一個典型的TRACE語句:


    …


       int nCount =9;


       CString strDesc("total");


       TRACE("Count =%d,Description =%s\n",nCount,strDesc);


       …


 


可以看到,TRACE語句的工作方式有點像C語言中的printf語句,TRACE宏參數的個數是可變的,因此使用起來非常容易。如果查看MFC的源代碼,你根本找不到TRACE宏,而只能看到TRACE0、TRACE1、TRACE2和TRACE3宏,它們的參數分別爲0、1、2、3。


個人總結:最近看網絡編程是碰到了TRACE語句,不知道在哪裏輸出,查了一晚上資料也沒找出來,今天終於找到了,方法如下:


1.在MFC中加入TRACE語句


2.在TOOLS->MFCTRACER中選擇 “ENABLE TRACING”點擊OK


3.進行調試運行,GO(F5)(特別注意:不是執行‘!’以前之所以不能看到TRACE內容,是因爲不是調試執行,而是‘!’了,切記,切記) 


4.然後就會在OUTPUT中的DEBUG窗口中看到TRACE內容了,調試執行會自動從BUILD窗口跳到DEBUG窗口,在那裏就看到TRACE的內容了,^_^


以下是找的TRACE的詳細介紹:


 ==============================


      TRACE宏對於VC下程序調試來說是很有用的東西,有着類似printf的功能;該宏僅僅在程序的DEBUG版本中出現,當RELEASE的時候該宏就完全消失了,從而幫助你調式也在RELEASE的時候減少代碼量。


使用非常簡單,格式如下:


TRACE("DDDDDDDDDDD");


TRACE("wewe%d",333);


同樣還存在TRACE0,TRACE1,TRACE2。。。分別對應0,1,2。。個參數


TRACE信息輸出到VC IDE環境的輸出窗口(該窗口是你編譯項目出錯提示的哪個窗口),但僅限於你在VC中運行你的DEBUG版本的程序。


TRACE信息還可以使用DEBUGVIEW來捕獲到。這種情況下,你不能在VC的IDE環境中運行你的程序,而將BUILD好的DEBUG版本的程序單獨運行,這個時候可以在DEBUGVIEW的窗口看到DEBUGVIE格式的輸出了。


VC中TRACE的用法有以下四種:


TRACE1 ,就是不帶動態參數輸出字符串,  類似C的printf("輸出字符串"); 


TRACE2: 中的字符串可以帶一個參數輸出 ,類似C的printf("...%d",變量);


TRACE3:可以帶兩個參數輸出,類似C的printf("...%d...%f",變量1,變量2);


TRACE4 可以帶三個參數輸出,類似C的printf("...%d,%d,%d",變量1,變量2,變量3);


TRACE 宏有點象我們以前在C語言中用的Printf函數,使程序在運行過程中輸出一些調試信息,使我們能瞭解程序的一些狀態。但有一點不同的是:
TRACE 宏只有在調試狀態下才有所輸出,而以前用的Printf 函數在任何情況下都有輸出。和Printf 函數一樣,TRACE函數可以接受多個參數如:


int x = 1;
int y = 16;
float z = 32.0;
TRACE( "This is a TRACE statement\n" );
TRACE( "The value of x is %d\n", x );
TRACE( "x = %d and y = %d\n", x, y );
TRACE( "x = %d and y = %x and z = %f\n", x, y, z );


要注意的是TRACE宏只對Debug 版本的工程產生作用,在Release 版本的工程中,TRACE宏將被忽略。


三、ASSERT宏


如果你設計了一個函數,該函數需要一個指向文檔對象的指針做參數,但是你卻錯誤地用一個視圖指針調用了這個函數。這個假的地址將導致視數據的破壞。現在,這種類型的問題可以被完全避免,只要在該函數的開始處實現一個ASSERT測試,用來檢測該指針是否真正指向一個文檔對象。一般來講,編程者在每個函數的開始處均應例行公事地使用assertion。ASSERT宏將會判斷表達式,如果一個表達式爲真,執行將繼續,否則,程序將顯示一條消息並且暫停,你可以選擇忽視這條錯誤並繼續、終止這個程序或者是跳到Debug器中。下面一例演示瞭如何使用一個ASSERT宏去驗證一個語句。


void foo(char p, int size )  


       {


      ASSERT( p != 0 ); //確認緩衝區的指針是有效的


     ASSERT( ( size >= 100  ); //確認緩衝區至少有100個字節


         // Do the foo calculation


}


這些語句不產生任何代碼,除非—DEBUG處理器標誌被設置。Visual C++只在Debug版本設置這些標誌,而在Release版本不定義這些標誌。當—DEBUG被定義時,兩個assertions將產生如下代碼:


//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);


 


Do-while循環將整個assertion封裝在一個單獨的程序塊中,使得編譯器編譯起來很舒暢。If語句將求取表達式的值並且當結果爲零時調用AfxAssertFailedLine()函數。這個函數將彈出一個對話框,其中提供三個選項“取消、重試或忽略”,當你選取“重試”時,它將返回TRUE。重試將導致對AfxDebugBreak()函數的調用,從而激活調試器。


AfxAssertFailedLine()是一個未正式公佈的函數,它的功能就是顯示一個消息框。該函數的源代碼駐留在afxasert.cpp中。函數中的—FILE—和—LINE—語句是處理器標誌,它們分別指定了源文件名和當前的行號。


 


AfxAssertFailedLine()是一個未正式公佈的函數,它的功能就是顯示一個消息框。該函數的源代碼駐留在afxasert.cpp中。函數中的—FILE—和—LINE—語句是處理器標誌,它們分別指定了源文件名和當前的行號。


 


四、VERIFY 宏


 


因爲assertion只能在程序的Debug版本中起作用,在表達式中不可以包含賦值語句、增加語句(++)或者是減少語句(--),因爲,這些語句實際改變數據。可有時你可能想要驗證一個能動的表達式,使用一個賦值語句。那麼就到了用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宏仍然測試表達式而assertion卻不起任何作用。可以說,在Release模式下,ASSERT語句被刪除了。


 


請注意,如果你在一個ASSERT語句中錯誤地使用了一個能動的表達式,編譯器將不做任何警告地忽略它。在Release模式下,該表達式就會被無聲息地刪除掉,這將會導致程序的錯誤運行。由於Release版的程序通常不包含Debug信息,這類錯誤將很難被發現。


五、VC高級調試方法-條件及數據斷點的設定


(一)位置斷點(LocationBreakpoint) 
  大家最常用的斷點是普通的位置斷點,在源程序的某一行按F9就設置了一個位置斷點。但對於很多問題,這種樸素的斷點作用有限。譬如下面這段代碼:


void CForDebugDlg::OnOK()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章