午夜精品福利视频,亚洲激情专区,免费看a网站,aa毛片,亚洲色图激情小说,亚洲一级毛片,免费一级毛片一级毛片aa

VC調(diào)試篇 -管理資料

管理資料 時(shí)間:2019-01-01 我要投稿
【www.stanzs.com - 管理資料】

    難怪很多前輩說調(diào)試是一個(gè)程序員最基本的技能,其重要性甚至超過學(xué)習(xí)一門語言,

VC調(diào)試篇

。不會(huì)調(diào)試的程序員就意味著他即使會(huì)一門語言,卻不能編制出任何好的軟件。

    我以前接觸的程序大多是有比較成形的思路和方法,調(diào)試起來出的問題都比較小,最近這個(gè)是我自己慢慢摸索調(diào)試,接觸了很多新的調(diào)試方法,并查了很多前輩的總結(jié),受益匪淺,總結(jié)以前的和新的收獲如下:

    VC調(diào)試篇

   

    設(shè)置

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

    為了增加調(diào)試信息,可以按照下述步驟進(jìn)行:

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

選擇C/C++頁,Category中選擇general,則出現(xiàn)一個(gè)Debug Info下拉列表框,可供選擇的調(diào)試信息方式包括:

   

    命令行

    Project settings

    說明

    無

    None

    沒有調(diào)試信息

    /Zd

    Line Numbers Only

    目標(biāo)文件或者可執(zhí)行文件中只包含全局和導(dǎo)出符號(hào)以及代碼行信息,不包含符號(hào)調(diào)試信息

    /Z7

    C 7.0- Compatible

    目標(biāo)文件或者可執(zhí)行文件中包含行號(hào)和所有符號(hào)調(diào)試信息,包括變量名及類型,函數(shù)及原型等

    /Zi

    Program Database

    創(chuàng)建一個(gè)程序庫(PDB),包括類型信息和符號(hào)調(diào)試信息。

    /ZI

    Program Database for Edit and Continue

    除了前面/Zi的功能外,這個(gè)選項(xiàng)允許對(duì)代碼進(jìn)行調(diào)試過程中的修改和繼續(xù)執(zhí)行。這個(gè)選項(xiàng)同時(shí)使#pragma設(shè)置的優(yōu)化功能無效

選擇Link頁,選中復(fù)選框"Generate Debug Info",這個(gè)選項(xiàng)將使連接器把調(diào)試信息寫進(jìn)可執(zhí)行文件和DLL

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

    調(diào)試方法:

    1、使用Assert(原則:盡量簡(jiǎn)單)assert只在debug下生效,release下不會(huì)被編譯。

    2、防御性的編程

    3、使用Trace

    4、用GetLastError來檢測(cè)返回值,通過得到錯(cuò)誤代碼來分析錯(cuò)誤原因

    5、把錯(cuò)誤信息記錄到文件中

    位置斷點(diǎn)(Location Breakpoint

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

    void CForDebugDlg::OnOK()

    {

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

    {

    int k = i * 10 - 2;//B

    SendTo(k);//C

    int tmp = DoSome(i);//D

    int j = i / tmp;//E

    }

    }

   

    執(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(1000-487)次時(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ì)檢測(cè)一個(gè)變量何時(shí)被修改很方便,特別對(duì)一些大程序。

    用好位置斷點(diǎn)的修飾條件,可以大大方便解決某些問題。

    數(shù)據(jù)斷點(diǎn)(Data Breakpoint

    軟件調(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[])

    {

    char szName1[10];

    char szName2[4];

    strcpy(szName1,"shenzhen");

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

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

    printf("%s", szName1);

    printf("%s", szName2);

    return 0;

    }

    這段程序的輸出是

    szName1: shenzhen

    szName1: ase

    szName2: vckbase

    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,

管理資料

VC調(diào)試篇》(http://www.stanzs.com)。

    數(shù)據(jù)斷點(diǎn)不只是對(duì)變量改變有效,還可以設(shè)置變量是否等于某個(gè)值。譬如,你可以將Figure 2中紅圈處改為條件”szName2[0]==""""y""""“,那么當(dāng)szName2第一個(gè)字符為y時(shí)斷點(diǎn)就會(huì)啟動(dòng)。

    可以看出,數(shù)據(jù)斷點(diǎn)相對(duì)位置斷點(diǎn)一個(gè)很大的區(qū)別是不用明確指明在哪一行代碼設(shè)置斷點(diǎn)。

    其他調(diào)試手段:系統(tǒng)提供一系列特殊的函數(shù)或者宏來處理Debug版本相關(guān)的信息,如下:

    宏名/函數(shù)名

    說明

    TRACE

    使用方法和printf完全一致,他在output框中輸出調(diào)試信息

    ASSERT

    它接收一個(gè)表達(dá)式,如果這個(gè)表達(dá)式為TRUE,則無動(dòng)作,否則中斷當(dāng)前程序執(zhí)行。對(duì)于系統(tǒng)中出現(xiàn)這個(gè)宏 導(dǎo)致的中斷,應(yīng)該認(rèn)為你的函數(shù)調(diào)用未能滿足系統(tǒng)的調(diào)用此函數(shù)的前提條件。例如,對(duì)于一個(gè)還沒有創(chuàng)建的窗口調(diào)用SetWindowText等。

    VERIFY

    和ASSERT功能類似,所不同的是,在Release版本中,ASSERT不計(jì)算輸入的表達(dá)式的值,而VERIFY計(jì)算表達(dá)式的值。

   

   

    Watch

    VC支持查看變量、表達(dá)式和內(nèi)存的值。所有這些觀察都必須是在斷點(diǎn)中斷的情況下進(jìn)行。

    觀看變量的值最簡(jiǎn)單,當(dāng)斷點(diǎn)到達(dá)時(shí),把光標(biāo)移動(dòng)到這個(gè)變量上,停留一會(huì)就可以看到變量的值。

    VC提供一種被成為Watch的機(jī)制來觀看變量和表達(dá)式的值。在斷點(diǎn)狀態(tài)下,在變量上單擊右鍵,選擇Quick Watch,就彈出一個(gè)對(duì)話框,顯示這個(gè)變量的值。

    單擊Debug工具條上的Watch按鈕,就出現(xiàn)一個(gè)Watch視圖(Watch1,Watch2,Watch3,Watch4),在該視圖中輸入變量或者表達(dá)式,就可以觀察變量或者表達(dá)式的值。注意:這個(gè)表達(dá)式不能有副作用,例如++運(yùn)算符絕對(duì)禁止用于這個(gè)表達(dá)式中,因?yàn)檫@個(gè)運(yùn)算符將修改變量的值,導(dǎo)致軟件的邏輯被破壞。

    Memory

    由于指針指向的數(shù)組,Watch只能顯示第一個(gè)元素的值。為了顯示數(shù)組的后續(xù)內(nèi)容,或者要顯示一片內(nèi)存的內(nèi)容,可以使用memory功能。在Debug工具條上點(diǎn)memory按鈕,就彈出一個(gè)對(duì)話框,在其中輸入地址,就可以顯示該地址指向的內(nèi)存的內(nèi)容。

    Varibles

    Debug工具條上的Varibles按鈕彈出一個(gè)框,顯示所有當(dāng)前執(zhí)行上下文中可見的變量的值。特別是當(dāng)前指令涉及的變量,以紅色顯示。

    寄存器

    Debug工具條上的Reigsters按鈕彈出一個(gè)框,顯示當(dāng)前的所有寄存器的值。

   

    調(diào)試技巧

    1、VC++中F5進(jìn)行調(diào)試運(yùn)行

    a)、在output Debug窗口中可以看到用TRACE打印的信息

    b)、Call Stack窗口中能看到程序的調(diào)用堆棧

    2、當(dāng)Debug版本運(yùn)行時(shí)發(fā)生崩潰,選擇retry進(jìn)行調(diào)試,通過看Call Stack分析出錯(cuò)的位置及原因

    3、使用映射文件調(diào)試

    a)、創(chuàng)建映射文件:Project settings中l(wèi)ink項(xiàng),選中Generate mapfile,輸出程序代碼地址:/MAPINFO: LINES,得到引出序號(hào):/MAPINFO: EXPORTS。

    b)、程序發(fā)布時(shí),應(yīng)該把所有模塊的映射文件都存檔。

    c)、查看映射文件:見” 通過崩潰地址找出源代碼的出錯(cuò)行”文件。

    4、可以調(diào)試的Release版本

    Project settings中C++項(xiàng)的Debug Info選擇為Program Database,Link項(xiàng)的Debug中選擇Debug Info和Microsoft format。

    5、查看API的錯(cuò)誤碼,在watch窗口輸入@err可以查看或者@err,hr,其中”,hr”表示錯(cuò)誤碼的說明。

    6、Set Next Statement:該功能可以直接跳轉(zhuǎn)到指定的代碼行執(zhí)行,一般用來測(cè)試異常處理的代碼。

    7、調(diào)試內(nèi)存變量的變化:當(dāng)內(nèi)存發(fā)生變化時(shí)停下來。???

    進(jìn)程控制

    VC允許被中斷的程序繼續(xù)運(yùn)行、單步運(yùn)行和運(yùn)行到指定光標(biāo)處,分別對(duì)應(yīng)快捷鍵F5、F10/F11和CTRL+F10。各個(gè)快捷鍵功能如下:

   

    快捷鍵

    說明

    F5

    調(diào)試/繼續(xù)運(yùn)行

    F10

    單步,如果涉及到子函數(shù),不進(jìn)入子函數(shù)內(nèi)部

    F11

    單步,如果涉及到子函數(shù),進(jìn)入子函數(shù)內(nèi)部

    CTRL+F10

    運(yùn)行到當(dāng)前光標(biāo)處。

    F7

    重建

    F9

    設(shè)置斷點(diǎn)/清除斷點(diǎn)

    Ctrl+Shift+F9

    清除所有斷點(diǎn)

    Shift+F5

    結(jié)束調(diào)試

    Call Stack

    調(diào)用堆棧反映了當(dāng)前斷點(diǎn)處函數(shù)是被那些函數(shù)按照什么順序調(diào)用的。單擊Debug工具條上的Call stack就顯示Call Stack對(duì)話框。在CallStack對(duì)話框中顯示了一個(gè)調(diào)用系列,最上面的是當(dāng)前函數(shù),往下依次是調(diào)用函數(shù)的上級(jí)函數(shù)。單擊這些函數(shù)名可以跳到對(duì)應(yīng)的函數(shù)中去。

    關(guān)注

    一個(gè)好的程序員不應(yīng)該把所有的判斷交給編譯器和調(diào)試器,應(yīng)該在程序中自己加以程序保護(hù)和錯(cuò)誤定位,具體措施包括:

對(duì)于所有有返回值的函數(shù),都應(yīng)該檢查返回值,除非你確信這個(gè)函數(shù)調(diào)用絕對(duì)不會(huì)出錯(cuò),或者不關(guān)心它是否出錯(cuò)。

一些函數(shù)返回錯(cuò)誤,需要用其他函數(shù)獲得錯(cuò)誤的具體信息。例如accept返回INVALID_SOCKET表示accept失敗,為了查明具體的失敗原因,應(yīng)該立刻用WSAGetLastError獲得錯(cuò)誤碼,并針對(duì)性的解決問題。

有些函數(shù)通過異常機(jī)制拋出錯(cuò)誤,應(yīng)該用TRY-CATCH語句來檢查錯(cuò)誤

程序員對(duì)于能處理的錯(cuò)誤,應(yīng)該自己在底層處理,對(duì)于不能處理的,應(yīng)該報(bào)告給用戶讓他們決定怎么處理。如果程序出了異常,卻不對(duì)返回值和其他機(jī)制返回的錯(cuò)誤信息進(jìn)行判斷,只能是加大了找錯(cuò)誤的難度。

    另外:VC中要編制程序不應(yīng)該一開始就寫cpp/h文件,而應(yīng)該首先創(chuàng)建一個(gè)合適的工程。因?yàn)橹挥羞@樣,VC才能選擇合適的編譯、連接選項(xiàng)。對(duì)于加入到工程中的cpp文件,應(yīng)該檢查是否在第一行顯式的包含stdafx.h頭文件,這是Microsoft Visual Studio為了加快編譯速度而設(shè)置的預(yù)編譯頭文件。在這個(gè)#include "stdafx.h"行前面的所有代碼將被忽略,所以其他頭文件應(yīng)該在這一行后面被包含。

    對(duì)于.c文件,由于不能包含stdafx.h,因此可以通過Project settings把它的預(yù)編譯頭設(shè)置為“不使用”,方法是:

彈出Project settings對(duì)話框

選擇C/C++

Category選擇Precompilation Header

選擇不使用預(yù)編譯頭。

    便于調(diào)試的代碼風(fēng)格

    不用全局變量

    所有變量都要初始化,成員變量在構(gòu)造函數(shù)中初始化

    盡量使用const

    詳盡的注釋

    總結(jié)

    調(diào)試最重要的還是你要思考,要猜測(cè)你的程序可能出錯(cuò)的地方,然后運(yùn)用你的調(diào)試器來證實(shí)你的猜測(cè)。

    來自:VC調(diào)試篇

最新文章