調(diào)試程序的簡(jiǎn)單說(shuō)明_第1頁(yè)
調(diào)試程序的簡(jiǎn)單說(shuō)明_第2頁(yè)
調(diào)試程序的簡(jiǎn)單說(shuō)明_第3頁(yè)
已閱讀5頁(yè),還剩5頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、難怪很多前輩說(shuō)調(diào)試是一個(gè)程序員最基本的技能 ,其重要性甚至超過(guò)學(xué)習(xí)一門語(yǔ)言。不會(huì)調(diào)試的程序員就意味著他即使會(huì)一門語(yǔ)言 ,卻不能編制出任何好的軟件。我以前接觸的程序大多是有比較成形的思路和方法,調(diào)試起來(lái)出的問(wèn)題都比較小 ,最近這個(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è)

2、計(jì)者可以在任意的Configuration 中增加調(diào)試信息 ,包括 Release版本。為了增加調(diào)試信息 ,可以按照下述步驟進(jìn)行 :?打開 Project settings對(duì)話框 (可以通過(guò)快捷鍵ALT+F7 打開 ,也可以通過(guò) IDE 菜單 Project/Settings 打開?選擇 C/C+頁(yè),Category 中選擇 general ,則出現(xiàn)一個(gè) Debug Info 下拉列表框 ,可供選擇的調(diào)試信息 方式包括 :命令行 Project settings說(shuō)明無(wú) None 沒有調(diào)試信息/Zd Line Numbers Only 目標(biāo)文件或者可執(zhí)行文件中只包含全局和導(dǎo)出符號(hào)以及代碼行信息

3、,不包含符號(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è)程序庫(kù) (PDB,包括類型信息和符號(hào)調(diào)試信息。/ZI Program Database for Edit and Continue除了前面 /Zi 的功能外 ,這個(gè)選項(xiàng)允許對(duì)代碼進(jìn)行調(diào)試過(guò)程中的修改和繼續(xù)執(zhí)行。這個(gè)選項(xiàng)同時(shí)使#pragma 設(shè)置的優(yōu)化功能無(wú)效?選擇 Link 頁(yè),選中復(fù)選框 "Generate Debug Info",這個(gè)選項(xiàng)將使連接器把調(diào)試信息寫進(jìn)可執(zhí)行文件和D

4、LL?如果 C/C+頁(yè)中設(shè)置了 Program Database以上的選項(xiàng) ,則 Linkincrementally 可以選擇。選中這個(gè)選項(xiàng) ,將使程序可以在上一次編譯的基礎(chǔ)上被編譯 (即增量編譯 ,而不必每次都從頭開始編譯。 調(diào)試方法 :1、使用 Assert(原則 :盡量簡(jiǎn)單 assert只在 debug下生效 ,release下不會(huì)被編譯。2、防御性的編程3、使用 Trace4、用 GetLastError 來(lái)檢測(cè)返回值 ,通過(guò)得到錯(cuò)誤代碼來(lái)分析錯(cuò)誤原因5、把錯(cuò)誤信息記錄到文件中位置斷點(diǎn) (Location Breakpoint大家最常用的斷點(diǎn)是普通的位置斷點(diǎn),在源程序的某一行按F9 就

5、設(shè)置了一個(gè)位置斷點(diǎn)。但對(duì)于很多問(wèn)題,這種樸素的斷點(diǎn)作用有限。譬如下面這段代碼:void CForDebugDlg:OnOK(for (int i = 0; i < 1000; i+ /Aint k = i * 10 - 2; /BSendTo(k; /Cint tmp = DoSome(i; /Dint j = i / tmp; /E執(zhí)行此函數(shù) ,程序崩潰于 E 行,發(fā)現(xiàn)此時(shí) tmp 為 0,假設(shè) tmp 本不應(yīng)該為 0,怎么這個(gè)時(shí)候?yàn)?0 呢?所以最好能夠跟蹤此次循環(huán)時(shí) DoSome 函數(shù)是如何運(yùn)行的 ,但由于是在循環(huán)體內(nèi) ,如果在 E 行設(shè)置斷點(diǎn) ,可能需要按 F5(GO 許多次。這

6、樣手要不停的按 ,很痛苦。使用 VC6 斷點(diǎn)修飾條件就可以輕易解決此問(wè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)后跟隨一串說(shuō)明 :.487 times remaining。意思是還剩下 487 次沒有執(zhí)行 ,那就是說(shuō)執(zhí)行到 513(1000-487 次時(shí)候出錯(cuò)的。因此 ,我們按步驟 2 所講 ,更改此

7、斷點(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í)程序停下來(lái) ,我們就可以輸入在編輯框中輸入 “i=100?!绷硗?,如果在此編輯框中如果只輸入變量名稱 ,則變量發(fā)生改變

8、時(shí) ,斷點(diǎn)才會(huì)啟動(dòng)。這對(duì)檢測(cè)一個(gè)變量何時(shí)被修改很方便 ,特別對(duì)一些大程序。用好位置斷點(diǎn)的修飾條件,可以大大方便解決某些問(wèn)題。數(shù)據(jù)斷點(diǎn) (Data Breakpoint軟件調(diào)試過(guò)程中 ,有時(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ù)被修改 (最好使用內(nèi)存來(lái)查找 ,使用變量名的話 ,IDE 不一定能找到。譬如下面一段程序 :#include "stdafx.h"#includeint main(int argc, char*

9、 argvchar szName110;char szName24;strcpy(szName1,"shenzhen"printf("%sn", szName1; /Astrcpy(szName2,"vckbase" /Bprintf("%sn", szName1;printf("%sn", szName2;return 0;這段程序的輸出是szName1: shenzhenszName1: aseszName2: vckbaseszName1何時(shí)被修改呢 ?因?yàn)闆]有明顯的修改szName1代碼

10、。我們可以首先在A 行設(shè)置普通斷點(diǎn) ,F5 運(yùn)行程序 ,程序停在 A 行。然后我們?cè)僭O(shè)置一個(gè)數(shù)據(jù)斷點(diǎn)。如下圖 :Figure 2 數(shù)據(jù)斷點(diǎn)F5 繼續(xù)運(yùn)行 ,程序停在 B 行,說(shuō)明 B 處代碼修改了 szName1。B 處明明沒有修改szName1呀 ?但調(diào)試器指明是這一行 ,一般不會(huì)錯(cuò) ,所以還是靜下心來(lái)看看程序 ,哦,你發(fā)現(xiàn)了 :szName2只有 4 個(gè)字節(jié) ,而 strcpy 了 7 個(gè)字節(jié) ,所以覆寫了 szName1。數(shù)據(jù)斷點(diǎn)不只是對(duì)變量改變有效,還可以設(shè)置變量是否等于某個(gè)值。譬如,你可以將 Figure 2 中紅圈處改為條件 ”szName20='''

11、9;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ǎn)設(shè)置最好用內(nèi)存地址來(lái)表示,否則 vc 會(huì)出錯(cuò)。其他調(diào)試手段 :系統(tǒng)提供一系列特殊的函數(shù)或者宏來(lái)處理Debug 版本相關(guān)的信息,如下 :宏名 /函數(shù)名說(shuō)明TRACE 使用方法和 printf 完全一致 ,他在 output 框中輸出調(diào)試信息ASSERT 它接收一個(gè)表達(dá)式 ,如果這個(gè)表達(dá)式為TRUE, 則無(wú)動(dòng)作 ,否則中斷當(dāng)前程序執(zhí)行。對(duì)于系統(tǒng)中出現(xiàn)這個(gè)宏導(dǎo)致的中斷,應(yīng)該認(rèn)為你的函數(shù)調(diào)用未能滿足系統(tǒng)的

12、調(diào)用此函數(shù)的前提條件。例如,對(duì)于一個(gè)還沒有創(chuàng)建的窗口調(diào)用SetWindowTextVERIFY 等。 和 ASSERT 功能類似, 所不同的是, Release版本中, 在ASSERT 不計(jì)算輸入的表達(dá)式的值,而VERIFY 計(jì)算表達(dá)式的值。使用 _ASSETE來(lái) debug,這三個(gè)都是 MFC 的。 _ASSERTE 的頭文件是 crtdbg.h。 值 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ī)制來(lái)觀看變量和表達(dá)

13、式的值。在斷點(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)致 軟件的邏輯 被破壞。 也可以修改某個(gè)變量的值。 Memory 由于指針指向的數(shù)組, Watch 只能顯示第一個(gè)元素的值。為了顯示數(shù)組的后續(xù)內(nèi) 容,或者要顯示一片內(nèi)存的內(nèi)容,可以使用

14、 memory 功能。在 Debug 工具條上點(diǎn) memory 按鈕,就彈出一個(gè)對(duì)話框,在其中輸入地址,就可以顯示該地址指向的內(nèi)存的內(nèi)容。 Variables Debug 工具條上的 Variables 按鈕彈出一個(gè)框,顯示所有當(dāng)前執(zhí)行上下文中可見 的變量的值。特別是當(dāng)前指令涉及的變量,以紅色顯示。 寄存器 Debug 工具條上的 Registers按鈕彈出一個(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 版本

15、運(yùn)行時(shí)發(fā)生崩潰,選擇 retry 進(jìn)行調(diào)試,通過(guò)看 Call Stack 分析出錯(cuò)的位置及原因3、使用映射文件調(diào)試 a、創(chuàng)建映射文件: Project settings中 link 項(xiàng),選中 Generate mapfile,輸 出程序代碼地址: /MAPINFO: LINES ,得到引出序號(hào): /MAPINFO: EXPORTS 。 b、程序發(fā)布時(shí),應(yīng)該把所有模塊的映射文件都存檔。c、查看映射文件:見 ”通過(guò)崩潰地址找出源代碼的出錯(cuò)行”文件。 4、可以調(diào)試的Release版本 Project settings中 C+項(xiàng)的 Debug Info 選擇為 Program Database, Li

16、nk 項(xiàng)的 Debug 中選擇 Debug Info 和 Microsoft format 。 5、查看 API 的錯(cuò)誤碼,在watch 窗口輸入 err 可以查看或者err,hr,其 中” ,hr表”示錯(cuò)誤碼的說(shuō)明。6、SetNext Statement:該功能可以直接跳轉(zhuǎn)到指定的代碼行執(zhí)行,一般用來(lái)測(cè)試異常處理的代碼。7、調(diào)試內(nèi)存變量的變化:當(dāng)內(nèi)存發(fā)生變化時(shí)停下來(lái)。?進(jìn)程控制VC允許被中斷的程序繼續(xù)運(yùn)行、單步運(yùn)行和運(yùn)行到指定光標(biāo)處,分別對(duì)應(yīng)快捷鍵F5、F10/F11 和 CTRL+F10 。各個(gè)快捷鍵功能如下:快捷鍵 F5 F10 F11 CTRL+F10F7 F9 Ctrl+Shift+

17、F9 Shift+F5 說(shuō)明 調(diào)試 /繼續(xù)運(yùn)行 單步,如果涉及到子函數(shù),不進(jìn)入子函數(shù)內(nèi)部 單步,如果涉及到子函數(shù),進(jìn)入子函數(shù)內(nèi)部運(yùn)行到當(dāng)前光標(biāo)處。重建 設(shè)置斷點(diǎn) /清除斷點(diǎn) 清除所有斷點(diǎn) 結(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)該在程序中自己加 以程序保

18、護(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ì)性的解決問(wèn)題。 有些函數(shù)通過(guò)異常機(jī)制拋出錯(cuò)誤,應(yīng)該用TRY-CATCH 語(yǔ)句來(lái)檢查錯(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&q

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論