免费高清特黄a大片,九一h片在线免费看,a免费国产一级特黄aa大,国产精品国产主播在线观看,成人精品一区久久久久,一级特黄aa大片,俄罗斯无遮挡一级毛片

分享

VC調試方法大全

 浮 生 2011-07-22

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++->常規(guī)->警告等級)

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

7、 在Release中調試源代碼,project->setting->C/C++->debug info選擇programDataBase(中文版是項目->屬性->C/C++->常規(guī)->調試信息格式->用于“編輯并繼續(xù)”的程序數據庫),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)(特別注意:不是執(zhí)行‘!’以前之所以不能看到TRACE內容,是因為不是調試執(zhí)行,而是‘!’了,切記,切記)

4.然后就會在OUTPUT中的DEBUG窗口中看到TRACE內容了,調試執(zhí)行會自動從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環(huán)境的輸出窗口(該窗口是你編譯項目出錯提示的哪個窗口),但僅限于你在VC中運行你的DEBUG版本的程序。

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

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

TRACE1 ,就是不帶動態(tài)參數輸出字符串, 類似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函數,使程序在運行過程中輸出一些調試信息,使我們能了解程序的一些狀態(tài)。但有一點不同的是:
TRACE 宏只有在調試狀態(tài)下才有所輸出,而以前用的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

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

void foo(char p, int size )

{

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

ASSERT( ( size >= 100 ); //確認緩沖區(qū)至少有100個字節(jié)

// 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循環(huán)將整個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卻不起任何作用??梢哉f,在Release模式下,ASSERT語句被刪除了。

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

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

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

void CForDebugDlg::OnOK()

{

for(int i = 0; i < 1000; i++) //A

{

intk = i * 10 - 2; //B

SendTo(k); //C

inttmp = DoSome(i); //D

Trace0("這里要輸出的內容”);//在這里可以輸出一些有用的信息,你也可以輸出I的值,都是可以的

intj = i / tmp; //E

}

}

//其實我們還可以用其他方法調式也是一樣的,你可以用TRACE0宏來輸出循環(huán)中的每一個結果,我們也可以在debug中看見輸出的結果,當出現問題時,輸出的結果可能就不一樣了,我們可以分析一下debug中的結果找出問題的所在

執(zhí)行此函數,程序崩潰于E行,發(fā)現此時tmp為0,假設tmp本不應該為0,怎么這個時候為0呢?所以最好能夠跟蹤此次循環(huán)時DoSome函數是如何運行的,但由于是在循環(huán)體內,如果在E行設置斷點,可能需要按F5(GO)許多次。這樣手要不停的按,很痛苦。使用VC6斷點修飾條件就可以輕易解決此問題。步驟如下。
1 Ctrl+B打開斷點設置框,如下圖:

Figure 1設置高級位置斷點
2 然后選擇D行所在的斷點,然后點擊condition按鈕,在彈出對話框的最下面一個編輯框中輸入一個很大數目,具體視應用而定,這里1000就夠了。
3 按F5重新運行程序,程序中斷。Ctrl+B打開斷點框,發(fā)現此斷點后跟隨一串說明:...487 times remaining。意思是還剩下487次沒有執(zhí)行,那就是說執(zhí)行到513(1000-487)次時候出錯的。因此,我們按步驟2所講,更改此斷點的skip次數,將1000改為513。
4 再次重新運行程序,程序執(zhí)行了513次循環(huán),然后自動停在斷點處。這時,我們就可以仔細查看DoSome是如何返回0的。這樣,你就避免了手指的痛苦,節(jié)省了時間。
再看位置斷點其他修飾條件。如Figure 1所示,在“Enter the expression to be evaluated:”下面,可以輸入一些條件,當這些條件滿足時,斷點才啟動。譬如,剛才的程序,我們需要i為100時程序停下來,我們就可以輸入在編輯框中輸入“i==100”。
另外,如果在此編輯框中如果只輸入變量名稱,則變量發(fā)生改變時,斷點才會啟動。這對檢測一個變量何時被修改很方便,特別對一些大程序。
用好位置斷點的修飾條件,可以大大方便解決某些問題。
二) 數據斷點(DataBreakpoint
軟件調試過程中,有時會發(fā)現一些數據會莫名其妙的被修改掉(如一些數組的越界寫導致覆蓋了另外的變量),找出何處代碼導致這塊內存被更改是一件棘手的事情(如果沒有調試器的幫助)。恰當運用數據斷點可以快速幫你定位何時何處這個數據被修改。譬如下面一段程序:

#include "stdafx.h"

#include <string.h>

int main(int argc, char* argv[])

{

charszName1[10];

charszName2[4];

strcpy(szName1,"shenzhen");

printf("%s\n",szName1); //A

strcpy(szName2,"vckbase"); //B

printf("%s\n",szName1);

printf("%s\n",szName2);

return0;

}

這段程序的輸出是

szName1: shenzhen

szName1:ase

szName2:vckbase

首先我給你分析一下為什么會是這樣的結果呢!首先你在strcpy(szName1,"shenzhen");這個地方F9設置一個斷點,然后F5運行程序,這是程序會斷到我們設置的斷點,如下圖

看到了吧,問題出現的原因就在這里,系統給szName2分配的地址是0x0012ff70這里是4個字節(jié),然后呢,在0x0012ff70后面4個字節(jié)處,開始分配szName1這10個字節(jié),也就是在0x0012ff74處開始分配10個字節(jié),

F10單步跟蹤,來到printf("%s\n", szName1)這一行,如下圖

szName1分配的空間已經附上了值.

F10走到下一個printf("%s\n", szName1) 看下圖,

因為szName1 和szName2分配的空間是連續(xù)的,所以給szName2賦值超過所容納的字節(jié)時就開始覆蓋szName1的內容了,所以說當我們在輸出結果的時候就出現我們想不到的結果了,

那么怎么去調試呢,下面是具體的方法

szName1何時被修改呢?因為沒有明顯的修改szName1代碼。我們可以首先在A行設置普通斷點,F5運行程序,程序停在A行。然后我們再設置一個數據斷點。如下圖:

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

三) 其他
1 在call stack窗口中設置斷點,選擇某個函數,按F9設置一個斷點。這樣可以從深層次的函數調用中迅速返回到需要的函數。
2 Set Next StateMent命令(debug過程中,右鍵菜單中的命令)
此命令的作用是將程序的指令指針(EIP)指向不同的代碼行。譬如,你正在調試上面那段代碼,運行在A行,但你不愿意運行B行和C行代碼,這時,你就可以在D行,右鍵,然后“Set Next StateMent”。調試器就不會執(zhí)行B、C行。只要在同一函數內,此指令就可以隨意跳前或跳后執(zhí)行。靈活使用此功能可以大量節(jié)省調試時間。
3 watch窗口
watch窗口支持豐富的數據格式化功能。如輸入0x65,u,則在右欄顯示101。
實時顯示windows API調用的錯誤:在左欄輸入@err,hr。
在watch窗口中調用函數。提醒一下,調用完函數后馬上在watch窗口中清除它,否則,單步調試時每一步調試器都會調用此函數。
4 messages斷點不怎么實用。基本上可以用前面講述的斷點代替。
六。VC調試環(huán)境設置

為了調試一個程序,首先必須使程序中包含調試信息。一般情況下,一個從AppWizard創(chuàng)建的工程中包含的Debug Configuration自動包含調試信息,但是是不是Debug版本并不是程序包含調試信息的決定因素,程序設計者可以在任意的Configuration中增加調試信息,包括Release版本。

為了增加調試信息,可以按照下述步驟進行:

 

打開Projectsettings對話框(可以通過快捷鍵ALT+F7打開,也可以通過IDE菜單Project/Settings打開)

選擇C/C++頁,Category中選擇general ,則出現一個Debug Info下拉列表框,可供選擇的調試信息 方式包括:

 

 

  命令行 Project settings 說明

無 None 沒有調試信息

/Zd Line Numbers Only 目標文件或者可執(zhí)行文件中只包含全局和導出符號以及代碼行信息,不包含符號調試信息

/Z7 C7.0- Compatible 目標文件或者可執(zhí)行文件中包含行號和所有符號調試信息,包括變量名及類型,函數及原型等

/Zi Program Database 創(chuàng)建一個程序庫(PDB),包括類型信息和符號調試信息。

/ZI Program Databasefor

Edit and Continue 除了前面/Zi的功能外,這個選項允許對代碼進行調試過程中的修改和繼續(xù)執(zhí)行。這個選項同時使#pragma設置的優(yōu)化功能無效

選擇Link頁,選中復選框"Generate DebugInfo",這個選項將使連接器把調試信息寫進可執(zhí)行文件和DLL

如果C/C++頁中設置了Program Database以上的選項,則Link incrementally可以選擇。選中這個選項,將使程序可以在上一次編譯的基礎上被編譯(即增量編譯),而不必每次都從頭開始編譯。

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多