VC++调试技巧学习总结
生活随笔
收集整理的這篇文章主要介紹了
VC++调试技巧学习总结
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
VC6.0調(diào)試方法
有時(shí)候,我們編寫好一個(gè)程序后,希望通過調(diào)試來知道變量值的變化情況,下面我和大家分享一下怎么利用VC6.0來查看變量值變化情況。工具/原料
VC6.0軟件、待測(cè)試程序
方法/步驟
1
打開你要調(diào)試代碼的工作空間。
2
按快捷鍵F5或點(diǎn)擊以下圖片上標(biāo)記的圖標(biāo)進(jìn)入調(diào)試模式。
3
打開調(diào)試工具條,一般情況下當(dāng)你按F5鍵后會(huì)自動(dòng)彈出,如果沒有彈出的話,右擊工具欄空白處,會(huì)彈出下圖,選中調(diào)試,就會(huì)出現(xiàn)調(diào)試工具條。
4
接下來,在監(jiān)視窗口中添加你要監(jiān)視數(shù)據(jù)變化的變量。
5
按F11逐語句的調(diào)試代碼,如果某一語句是一函數(shù),你不希望進(jìn)入該函數(shù)時(shí),F10逐過程來查看,在代碼的調(diào)試過程中,通過監(jiān)視窗口查看變量值的變化,從而確定代碼是否有問題。
6
如果希望跳出某一函數(shù)時(shí),按快捷鍵Shift+F11,或者直接點(diǎn)擊調(diào)試工具條上的按鈕就可以跳出該函數(shù)了。
7
如果只是希望調(diào)試某一部分代碼的話,可以設(shè)置斷點(diǎn)來調(diào)試,調(diào)試方法如上,只是在要調(diào)試的代碼之間用斷點(diǎn)來分開。設(shè)置斷點(diǎn)時(shí),光標(biāo)放在你要設(shè)置斷點(diǎn)的那行,按F9或點(diǎn)擊編譯微型條上面的類似
手狀的按鈕即可。
========
VC 6.0 調(diào)試技巧(二)
http://blog.csdn.net/dddd0216/article/details/513301631. Restart (Ctrl+shift+F5 ): 此debugger功能將從程序的開始(第一有效行)處全速執(zhí)行,而不是從當(dāng)前所跟蹤的位置開始調(diào)試,這時(shí)所有變量的當(dāng)前值都將被丟棄,debugger 會(huì)自動(dòng)停在程序的main()開始
處.這時(shí)如果選擇Step Over(F10)就可以逐步執(zhí)行main()函數(shù)了.
2. Stop Debugging (Shift+F5 ):此debugger功能將終止(所有)調(diào)試,并返回到常規(guī)編輯狀態(tài).?
3. Break (此功能常常在遇到調(diào)用函數(shù)的語句時(shí)可見 .): 此功能將在調(diào)試過程中的debugger當(dāng)前位置掛起程序的執(zhí)行,然后就可以在調(diào)試狀態(tài)一修改程序的代碼,接著可以用Apply Code Changes(Alt
+F10)來應(yīng)用修改的代碼到正在調(diào)試的程序當(dāng)中.如果,當(dāng)前(需要,待)可以(從DOS 等窗口)輸入值,掛起后將不能再輸入.
4. Apply Code Changes (Alt+F10 ):此功能可以在程序正在調(diào)試程序過程中應(yīng)用(掛起)修改后的源代碼.如,選擇Break功能并修改代碼后,只要選擇Apply Code Changes(Alt+F10)就能將修改后的代碼應(yīng)
用到正在調(diào)試的程序當(dāng)中.
5. Show Next Statement (Alt+Num* ):此功能將顯示程序代碼的下一條語句,如果源代碼中找不到,則在Disassembly窗口中顯示語句. 當(dāng)在Disassembly窗口中顯示時(shí),可以單擊Disassembly 返回到源代
碼窗口.
6. Step Into (F11 ):此功能可以單步進(jìn)入到在調(diào)試過程中所跟蹤的調(diào)用函數(shù)的語句的函數(shù)內(nèi)部.如,當(dāng)前語句是"d.Display()",?
選擇Step Into(F11)后,Debugger將進(jìn)入Display()函數(shù)內(nèi)部并停在Display()函數(shù)內(nèi)部的第一條語句上.(此時(shí), 就可以Step Over(F10)對(duì)Display()函數(shù)進(jìn)行單步調(diào)試了.)
7. Step Over (F10 ):此功能可以單步對(duì)所在函數(shù)單步調(diào)試,如果調(diào)試的語句是一個(gè)調(diào)用函數(shù)的語句時(shí), Debugger將全速執(zhí)行所調(diào)用的函數(shù),單步(一步)通過所調(diào)用的函數(shù),Debugger停該調(diào)用語句的下一條
語句上.
8. Step Out (Shift+F11 ):此功能將使Debugger切換回全速執(zhí)行到被調(diào)用函數(shù)結(jié)束,并停在該函數(shù)調(diào)用語句的下一條語句上. 當(dāng)確定所調(diào)用的函數(shù)沒有問題時(shí)可以用這個(gè)功能全速執(zhí)行被調(diào)用函數(shù).
9. Run to Cursor (Ctrl+F10 ):此功能將全速執(zhí)行到包含插入點(diǎn)光標(biāo)所在的行,可以作為在插入點(diǎn)光標(biāo)處設(shè)置常規(guī)斷點(diǎn)的一種選擇. 注意,當(dāng)光標(biāo)處不是一個(gè)有效的執(zhí)行語句時(shí)此功能將不起作用.
10. Go (F5 ):此功能將全速執(zhí)行程序直到遇到一個(gè)斷點(diǎn)或程序結(jié)束,或直到程序暫停等待用戶輸入. 注意,此功能最能有效的調(diào)試循環(huán),常將斷點(diǎn)設(shè)置在循環(huán)體內(nèi),重復(fù)的按F5全速執(zhí)行循環(huán)體可以測(cè)試循環(huán)過
程中的產(chǎn)生的變化.
11.Step Into Specific Function:此功能可以可以單步通過程序中的指令,并進(jìn)入指定的函數(shù)調(diào)用,此功能對(duì)于函數(shù)的嵌套層不限.
??
調(diào)試常用快捷鍵
單步進(jìn)入 ? ? ? ? ? ? ? F11
?
單步跳過 ? ? ? ? ? ? ?F10
?
單步跳出 ? ? ? ? ? ? ?SHIFT+F11
?
運(yùn)行到光標(biāo) ? ? ? ? ? CTRL+F10
?
開關(guān)斷點(diǎn) ? ? ? ? ? ? ?F9
?
清除斷點(diǎn) ? ? ? ? ? ? ?CTRL+SHIFT+F9
?
Breakpoints(斷點(diǎn)管理) ? ? ? ? ? ? ?CTRL+B 或ALT+F9
?
GO ? ? ? ? ? ? ? ? ? ? ? F5
?
Compile(編譯,生成.obj文件) ? ? ? CTRL+F7
?
Build(組建,先Compile生成.obj再Link生成.exe) ? ? ? ? ? ? ?F7
?
From 《Visual C++ Debugger》
?
From 《visual C++ 6.0開發(fā)工具與調(diào)試》
1、 ? ? ? ? ?如何快速地規(guī)范代碼縮進(jìn)格式
選中所需要規(guī)范的代碼,按shift+F8
2、 ? ? ? ? ?如何在Release狀態(tài)下進(jìn)行調(diào)試
Project->Setting=>ProjectSetting對(duì)話框,選擇Release狀態(tài)。C/C++標(biāo)簽中的Category選General,Optimizations選Disable(Debug),
Debut info選Program Database。在Link標(biāo)簽中選中Generate debug info復(fù)選框。
?
注:只是一個(gè)介乎Debug合Release的中間狀態(tài),所有的ASSERT、VERIFY都不起作用,函數(shù)調(diào)用方式已經(jīng)是真正的調(diào)用,而不查表,
但是這種狀態(tài)下QuickWatch、調(diào)用隊(duì)列跟蹤功能仍然有效,和Debug版一樣。
?
3、 ? ? ? ? ?Release和Debug有什么不同。
Release版稱為發(fā)行版,Debug版稱為調(diào)試版。
Debug中可以單步執(zhí)行、跟蹤等功能,但生成的可執(zhí)行文件比較大,代碼運(yùn)行速度較慢。Release版運(yùn)行速度較快,可執(zhí)行文件較小,
但在其編譯條件小無法執(zhí)行調(diào)試功能。
Release的exe文件鏈接的是標(biāo)準(zhǔn)的MFC DLL(Use MFC in a shared or static dll),比如MFC42.DLL。這些DLL在安裝Windows的時(shí)候,
已經(jīng)配置,所以這些程序能夠在沒有安裝Visual C++ 6.0的機(jī)器上運(yùn)行。而Debug版本的exe鏈接了調(diào)試版本的MFC DLL文件,如MFC42D.DLL。
在沒有安裝Visual C++6.0的機(jī)器上不能運(yùn)行,因?yàn)槿盡FC42D.DLL等,除非選擇use static dll when link。
?
4、 ? ? ? ? ?ASSERT和VERIFY有什么區(qū)別
ASSERT里面的內(nèi)容在Release版本中不編譯,VERIFY里面的內(nèi)容仍然翻譯,但不再判斷真假。所以后者更安全一點(diǎn)。
例如ASSERT(file.Open(strFileName))。
一旦到了Release版本中,這一行就忽略了,file根本就不Open()了,而且沒有任何出錯(cuò)的信息。如果用VERIFY()就不會(huì)有這個(gè)問題。
?
5、 ? ? ? ? ?Workspace和Project之間是什么樣的關(guān)系
每個(gè)Workspace可以包括幾個(gè)project,但只有一個(gè)處于Active狀態(tài),各個(gè)project之間可以有依賴關(guān)系,在project的Setting..中可以設(shè)定,
比如那個(gè)Active狀態(tài)的project可以依賴于其他的提供其函數(shù)調(diào)用的靜態(tài)庫。
?
6、 ? ? ? ? ?如何在非MFC程序中使用ClassWizard
在工程目錄下新建一個(gè)空的.RC文件,然后加入到工程中就可以了。
?
7、 ? ? ? ? ?如何設(shè)置斷點(diǎn)
按F9在當(dāng)前光標(biāo)處增加一個(gè)斷點(diǎn)和取消一個(gè)斷點(diǎn)。
另外,在編輯狀態(tài)下,按Ctrl+B組合鍵,彈出斷點(diǎn)設(shè)置對(duì)話框。然后單擊【Condition…】按鈕彈出設(shè)置斷點(diǎn)條件的對(duì)話框進(jìn)行設(shè)置。
?
8、 ? ? ? ? ?在編輯狀態(tài)下發(fā)現(xiàn)成員變量或函數(shù)不能顯示提示是如何打開顯示功能
這似乎是目前這個(gè)Visual C++ 6.0版本的一個(gè)bug,可按如下步驟使其正常,如再出現(xiàn),可如法炮制:
(1) ? ? ? ? ? ? 關(guān)閉Project
(2) ? ? ? ? ? ? 刪除"工程名.ncb"文件
(3) ? ? ? ? ? ? 重新打開工程
?
9、 ? ? ? ? ?如何將一個(gè)通過ClassWizard生成的類徹底刪除
首先在工作區(qū)的FileView中選中該類的.h和.cpp文件,按delete刪除,然后在文件管理器中將這兩個(gè)文件刪除,再運(yùn)行ClassWizard,
這時(shí)出現(xiàn)是否移走該類的提示,選擇remove就可以了。
?
10、 ? ? 如何將再workspace中消失的類找出來
打開該類對(duì)應(yīng)的頭文件,然后將其類名隨便改一下,這個(gè)時(shí)候工作區(qū)就會(huì)出現(xiàn)新的類,再將這個(gè)類改回原來的名字就可以了。
?
11、 ? ? 如何清除所有的斷點(diǎn)
菜單【Edit】->【Breakpoints…】,打開"Breakpoints"對(duì)話框,單擊【Remove All】按鈕即可。
快捷鍵是"Ctrl + Shift + F8"。
?
12、 ? ? 如何再ClassWizard中選擇未列出的信息
打開"ClassWizard"對(duì)話框,然后切換到"Class Info"頁面。改變"Message filter",如選擇"Window","Message"頁面就會(huì)出現(xiàn)Window的信息。
?
13、 ? ? 如何檢測(cè)程序中的括號(hào)是否匹配
把光標(biāo)移動(dòng)到需要檢測(cè)的括號(hào)前面,按快捷鍵"Ctrl + ]"。如果括號(hào)匹配正確,光標(biāo)就跳到匹配的括號(hào)處,否則光標(biāo)不移動(dòng),
并且機(jī)箱喇叭還會(huì)發(fā)出一聲警告。
?
14、 ? ? 如何查看一個(gè)宏(或變量、函數(shù))的定義
把光標(biāo)移動(dòng)到要查看的一個(gè)宏上,就比如說最常見的DECLARE_MAP_MESSAGE上按一下F12(或右鍵菜單中的相關(guān)菜單),
如果沒有建立瀏覽文件,就會(huì)出現(xiàn)提示對(duì)話框,按【確定】按鈕,然后就會(huì)跳到該宏(或變量、函數(shù))定義的地方。
?
15、 ? ? 如何添加Lib文件到當(dāng)前工程
單擊菜單【Project】->【Settings…】彈出"Project Setting"對(duì)話框,切換到"Link"標(biāo)簽頁,在"Object/library modules"處輸入Lib文件名稱,
不同的Lib之間用空格格開。
?
16、 ? ? 如何快速刪除項(xiàng)目下的Debug文件夾中臨時(shí)文件
在工作區(qū)的FileView視圖中選中對(duì)應(yīng)的項(xiàng)目,單擊右鍵彈出菜單,選擇【Clean(selection only)】菜單即可。
?
17、 ? ? 如何快速生成一個(gè)現(xiàn)有工程除了工程名外完全相同的新工程。
在新建工程的"New"對(duì)話框中選擇"Custom Appwizard"項(xiàng),輸入新工程的名字,單擊【OK】按鈕。出現(xiàn)"Custom AppWizard"項(xiàng),
輸入新工程的名字,單擊【OK】按鈕。出現(xiàn)"Custom AppWizard-Step 1 of 2"對(duì)話框,選擇"An existing Project"項(xiàng),單擊【Next】按鈕。
出現(xiàn)"Custom AppWizard-Step 2 of 2"對(duì)話框,選擇現(xiàn)有工程的工程文件名,最后單擊【Finish】按鈕。編譯后就生成一個(gè)與現(xiàn)有工程相同
但可以重新取名的工程AppWizard。
現(xiàn)在就可以項(xiàng)用MFC AppWizard一樣用這個(gè)定制的向?qū)АH绻幌胗昧?#xff0c;可以在Visual C++ 6.0安裝目錄下Common/MSDev98/Template目錄
中刪除該Wizard對(duì)應(yīng)的.awx和.pdb文件。
?
18、 ? ? 如何解決Visual C++ 6.0不正確連接的問題
情景:明明之間改動(dòng)了一個(gè)文件,卻要把整個(gè)項(xiàng)目全部重新編譯鏈接一次。剛剛鏈接好,一運(yùn)行,有提示重新編譯鏈接一次。
這是因?yàn)槌霈F(xiàn)了未來文件(修改時(shí)間和創(chuàng)建時(shí)間比系統(tǒng)時(shí)間晚)的緣故??梢赃@樣處理:找到工程文件夾下的debug目錄,
將創(chuàng)建和修改時(shí)間都比系統(tǒng)時(shí)間的文件全部刪除,然后再從新"Rebuild All"一次。
?
19、 ? ? 引起LNK2001的常見錯(cuò)誤都有哪些
遇到的LNK2001錯(cuò)誤主要為:unresolved external symbol "symbol"
如果鏈接程序不能在所有的庫和目標(biāo)文件內(nèi)找到所引用的函數(shù)、變量或標(biāo)簽,將產(chǎn)生此錯(cuò)誤信息。
一般來說,發(fā)生錯(cuò)誤的原因有兩個(gè):一時(shí)所引用的函數(shù)、變量不存在,拼寫不正確或者使用錯(cuò)誤;其次可能使用了不同版本的鏈接庫。
一下是可能產(chǎn)生LNK2001錯(cuò)誤的原因:
<1>由于編碼錯(cuò)誤導(dǎo)致的LNK2001錯(cuò)誤
1.不相匹配的程序代碼或模塊定義(.DEF)文件導(dǎo)致LNK2001。例如,如果在C++源文件了內(nèi)聲明了一變量"var1",?
卻視圖在另一個(gè)文件內(nèi)以變量"var1"訪問改變量。
(2) ? ? ? ? ? ? 如果使用的內(nèi)聯(lián)函數(shù)是在.cpp文件內(nèi)定義的,而不是在頭文件內(nèi)定義將導(dǎo)致LNK2001錯(cuò)誤。
(3) ? ? ? ? ? ? 調(diào)用函數(shù)是如果所用的參數(shù)類型頭函數(shù)聲明是的類型不符將會(huì)產(chǎn)生LNK2001錯(cuò)誤。
(4) ? ? ? ? ? ? 視圖從基類的構(gòu)造函數(shù)或析構(gòu)函數(shù)中調(diào)用虛擬函數(shù)時(shí)將會(huì)導(dǎo)致LNK2001錯(cuò)誤。
(5) ? ? ? ? ? ? 要注意函數(shù)和變量的可公用性,只有全局變量、函數(shù)時(shí)可公用的。靜態(tài)函數(shù)和靜態(tài)變量具有相同的使用范圍限制。
當(dāng)試圖從文件外部方位任何沒有在該文件內(nèi)聲明的靜態(tài)變量時(shí)將導(dǎo)致編譯錯(cuò)誤或LNK2001錯(cuò)誤。
<2>由于編譯和聯(lián)機(jī)的設(shè)置而造成的LNK2001錯(cuò)誤
1.如果編譯時(shí)使用的時(shí)/NOD(/NODERAULTLIB)選項(xiàng),程序所需要的運(yùn)行庫和MFC時(shí)將得到又編譯器寫入目標(biāo)文件模塊,?
但除非在文件中明確包含這些庫名,否則這些庫不會(huì)北鏈接進(jìn)工程文件。這種情況下使用/NOD將導(dǎo)致LNK2001錯(cuò)誤
2.如果沒有為wWinMainCRTStartup設(shè)定程序入口,在使用Unicode和MFC時(shí)講的到?
"unresolved external on _WinMain@16 "的LNK2001錯(cuò)誤信息。
3.使用/MD選項(xiàng)編譯時(shí),既然所有的運(yùn)行庫都被保留在動(dòng)態(tài)鏈接庫之內(nèi),源文件中對(duì)"func"的引用,?
在目標(biāo)文件里即對(duì)"__imp__func"的引用。如果試圖使用靜態(tài)庫LIBC.LIB或LIBCMT.LIB進(jìn)行鏈接,將在__imp__func上發(fā)生LNK2001錯(cuò)誤。如果不使用/MD選項(xiàng)編譯,在使用MSVCxx.LIB鏈接時(shí)也會(huì)發(fā)
生LNK2001錯(cuò)誤。
(4) ? ? ? ? ? ? 使用/ML選項(xiàng)編譯時(shí),如用LIBCMT.LIB鏈接回在_errno上發(fā)生LNK2001錯(cuò)誤。
(5) ? ? ? ? ? ? 當(dāng)編譯調(diào)試版的應(yīng)用程序時(shí),如果采用發(fā)行版模態(tài)庫進(jìn)行鏈接也會(huì)產(chǎn)生LNK2001錯(cuò)誤;同樣,
使用調(diào)試版模態(tài)庫鏈接發(fā)行版應(yīng)用程序時(shí)也會(huì)產(chǎn)生相同的錯(cuò)誤。
(6) ? ? ? ? ? ? 不同版本的庫和編譯器的混合使用也能產(chǎn)生問題,因?yàn)樾掳娴膸炖锟赡馨缦鹊陌姹緵]有的符號(hào)和說明。
(7) ? ? ? ? ? ? 在不同的模塊中使用內(nèi)聯(lián)和非內(nèi)聯(lián)的編譯選項(xiàng)能夠?qū)е翷NK2001錯(cuò)誤。如果創(chuàng)建C++庫時(shí)打開了
函數(shù)內(nèi)聯(lián)(/Ob1或/Ob2),但是在描述該函數(shù)的相應(yīng)頭問卷安里卻關(guān)閉了函數(shù)內(nèi)聯(lián)(沒有inline關(guān)鍵字),
只是將得到錯(cuò)誤信息。為避免該問題的發(fā)生,應(yīng)該在相應(yīng)的頭文件中用inline關(guān)鍵字標(biāo)志為內(nèi)聯(lián)函數(shù)。
(8) ? ? ? ? ? ? 不正確的/SUBSYSTEM或ENTRY設(shè)置也能導(dǎo)致LNK2001錯(cuò)誤。
?
20、 ? ? 如何調(diào)試一個(gè)沒有源碼的exe文件調(diào)用的dll
在Visual C++ 6.0中,進(jìn)入"Project Setting"對(duì)話框然后選擇Debug標(biāo)簽頁。通常Visual Studio默認(rèn)"executable for debug session"為可執(zhí)行文件名,
但可以將他改成任何你想要的程序。甚至可以指定不同的工作目錄以及傳遞參數(shù)到你的程序。這個(gè)技術(shù)常用來調(diào)試Dlls、名字空間擴(kuò)展、
COM對(duì)象和其他從某些EXE以及從第三方的EXE中調(diào)用的plug-in程序。
?
21、 ? ? Visual C++ 6.0工程中的項(xiàng)目文件都表示什么。
.opt:工程關(guān)于開發(fā)化境的參數(shù)文件。如工具條位置等信息。
.aps(AppStudio File)資源輔助文件,二進(jìn)制格式,一般不用去管他。
.clw:ClassWizard信息文件,實(shí)際上是INI文件格式,又興趣可以研究一下。有時(shí)候ClassWizard出了問題,手工修改CLW文件可以解決。
如果此文件不存在的話,每次用ClassWizard的時(shí)候回提示是否重建。
.dsp(DevelopStudio Project):項(xiàng)目文件,文本格式,不過不熟悉的或不要手工修改。
.dsw(DevelopStudio Workspace):是工作區(qū)文件,其他特點(diǎn)和.dsp差不多。
.plg:是編譯信息文件,編譯時(shí)的error和warning信息文件(實(shí)際上時(shí)一個(gè)html文件),一般用處不大。在單擊菜單【Tool】->【Option】
彈出的對(duì)話框里面有個(gè)選項(xiàng)可以控制這個(gè)文件的生成。
.hpj(Help Project):是生成幫助文件的工程,用microsoft Help Compiler可以處理。
.mdp(Microsoft DevStudio Project):是舊版本的項(xiàng)目文件,如果要打開此文件的話,回提示你是否轉(zhuǎn)換成新的.dsp格式。
.bsc:是用于瀏覽項(xiàng)目信息的,如果用Source Brower的話舊必須又這個(gè)文件。如果不用這個(gè)功能的話,可以在Project Options里面去掉
Generate Browse Info File,這樣可以加快編譯速度。
.map是執(zhí)行文件的影像信息記錄文件,除非對(duì)系統(tǒng)底層,這個(gè)文件一般用不著。
.pch(Pre-Compiled File):是與編譯文件,可以加快編譯速度,但是文件非常大。
.pdb(Program Database),記錄了程序有關(guān)的一些數(shù)據(jù)和調(diào)試信息,在調(diào)試的時(shí)候可能有用。
.exp:只有在編譯DLL的時(shí)候才會(huì)生成,記錄了DLL文件的一些信息,一般也沒有用。
.ncb:無編譯瀏覽文件(no compile browser)。當(dāng)自動(dòng)完成功能出問題時(shí)可以刪除此文件。編譯工程后回自動(dòng)生成。
========
VC++一些開發(fā)心得與調(diào)試技巧
http://www.cnblogs.com/maowang1991/p/3572329.html? ? ?1.如何在Release狀態(tài)下進(jìn)行調(diào)試
Project->Setting=>ProjectSetting對(duì)話框,選擇Release狀態(tài)。C/C++標(biāo)簽中的Category選General,Optimizations選Disable(Debug),Debut info選Program Database。在Link標(biāo)簽中選中
Generate debug info復(fù)選框。
注:只是一個(gè)介乎Debug和Release的中間狀態(tài),所有的ASSERT、VERIFY都不起作用,函數(shù)調(diào)用方式已經(jīng)是真正的調(diào)用,而不查表,但是這種狀態(tài)下QuickWatch、調(diào)用隊(duì)列跟蹤功能仍然有效,
和Debug版一樣。
2. Release和Debug有什么不同
Release版稱為發(fā)行版,Debug版稱為調(diào)試版。
Debug中可以單步執(zhí)行、跟蹤等功能,但生成的可執(zhí)行文件比較大,代碼運(yùn)行速度較慢。Release版運(yùn)行速度較快,可執(zhí)行文件較小,但在其編譯條件下無法執(zhí)行調(diào)試功能。
Release的exe文件鏈接的是標(biāo)準(zhǔn)的MFC DLL(Use MFC in a shared or static dll)。這些DLL在安裝Windows的時(shí)候,已經(jīng)配置,所以這些程序能夠在沒有安裝Visual C++ 6.0的機(jī)器上運(yùn)行。而
Debug版本的exe鏈接了調(diào)試版本的MFC DLL文件,在沒有安裝Visual C++6.0的機(jī)器上不能運(yùn)行,因?yàn)槿毕鄳?yīng)的DLL,除非選擇use static dll when link。
3. ASSERT和VERIFY有什么區(qū)別
ASSERT里面的內(nèi)容在Release版本中不編譯,VERIFY里面的內(nèi)容仍然翻譯,但不再判斷真假。所以后者更安全一點(diǎn)。
例如ASSERT(file.Open(strFileName))。
一旦到了Release版本中,這一行就忽略了,file根本就不Open()了,而且沒有任何出錯(cuò)的信息。如果用VERIFY()就不會(huì)有這個(gè)問題。
4.Workspace和Project之間是什么樣的關(guān)系
每個(gè)Workspace可以包括幾個(gè)project,但只有一個(gè)處于Active狀態(tài),各個(gè)project之間可以有依賴關(guān)系,在project的Setting..中可以設(shè)定,比如那個(gè)Active狀態(tài)的project可以依賴于其他的提供其
函數(shù)調(diào)用的靜態(tài)庫。
5. 如何在非MFC程序中使用ClassWizard
在工程目錄下新建一個(gè)空的.RC文件,然后加入到工程中就可以了。
6.如何設(shè)置斷點(diǎn)
按F9在當(dāng)前光標(biāo)處增加一個(gè)斷點(diǎn)和取消一個(gè)斷點(diǎn)。
另外,在編輯狀態(tài)下,按Ctrl+B組合鍵,彈出斷點(diǎn)設(shè)置對(duì)話框。然后單擊【Condition…】按鈕彈出設(shè)置斷點(diǎn)條件的對(duì)話框進(jìn)行設(shè)置。
7.在編輯狀態(tài)下發(fā)現(xiàn)成員變量或函數(shù)不能顯示提示是如何打開顯示功能
這似乎是目前這個(gè)Visual C++ 6.0版本的一個(gè)bug,可按如下步驟使其正常,如再出現(xiàn),可如法炮制:
(1)關(guān)閉Project
(2)刪除“工程名.ncb”文件
(3)重新打開工程
8.如何將一個(gè)通過ClassWizard生成的類徹底刪除
首先在工作區(qū)的FileView中選中該類的.h和.cpp文件,按delete刪除,然后在文件管理器中將這兩個(gè)文件刪除,再運(yùn)行ClassWizard,這時(shí)出現(xiàn)是否移走該類的提示,選擇remove就可以了。
9. 如何將在workspace中消失的類找出來
打開該類對(duì)應(yīng)的頭文件,然后將其類名隨便改一下,這個(gè)時(shí)候工作區(qū)就會(huì)出現(xiàn)新的類,再將這個(gè)類改回原來的名字就可以了。
10. 如何清除所有的斷點(diǎn)
菜單【Edit】->【Breakpoints…】,打開“Breakpoints”對(duì)話框,單擊【Remove All】按鈕即可??旖萱I是“Ctrl + Shift + F9”。
11. 如何再ClassWizard中選擇未列出的信息
打開“ClassWizard”對(duì)話框,然后切換到“Class Info”頁面。改變“Message filter”,如選擇“Window”,“Message”頁面就會(huì)出現(xiàn)Window的信息。
12. 如何檢測(cè)程序中的括號(hào)是否匹配
把光標(biāo)移動(dòng)到需要檢測(cè)的括號(hào)前面,按快捷鍵“Ctrl + ]”。如果括號(hào)匹配正確,光標(biāo)就跳到匹配的括號(hào)處,否則光標(biāo)不移動(dòng),并且機(jī)箱喇叭還會(huì)發(fā)出一聲警告。
13. 如何查看一個(gè)宏(或變量、函數(shù))的定義
把光標(biāo)移動(dòng)到要查看的一個(gè)宏上,就比如說最常見的DECLARE_MAP_MESSAGE上按一下F12(或右鍵菜單中的相關(guān)菜單),如果沒有建立瀏覽文件,就會(huì)出現(xiàn)提示對(duì)話框,按【確定】按鈕,然后就
會(huì)跳到該宏(或變量、函數(shù))定義的地方。
14. 如何添加Lib文件到當(dāng)前工程
單擊菜單【Project】->【Settings…】彈出“Project Setting”對(duì)話框,切換到“Link”標(biāo)簽頁,在“Object/library modules”處輸入Lib文件名稱,不同的Lib之間用空格格開。
15. 如何快速刪除項(xiàng)目下的Debug文件夾中臨時(shí)文件
在工作區(qū)的FileView視圖中選中對(duì)應(yīng)的項(xiàng)目,單擊右鍵彈出菜單,選擇【Clean(selection only)】菜單即可。
16. 如何快速生成一個(gè)現(xiàn)有工程除了工程名外完全相同的新工程
在新建工程的“New”對(duì)話框中選擇“Custom Appwizard”項(xiàng),輸入新工程的名字,單擊【OK】按鈕。出現(xiàn)“Custom AppWizard”項(xiàng),輸入新工程的名字,單擊【OK】按鈕。出現(xiàn)“Custom?
AppWizard-Step 1 of 2”對(duì)話框,選擇“An existing Project”項(xiàng),單擊【Next】按鈕。出現(xiàn)“Custom AppWizard-Step 2 of 2”對(duì)話框,選擇現(xiàn)有工程的工程文件名,最后單擊【Finish】按鈕。
編譯后就生成一個(gè)與現(xiàn)有工程相同但可以重新取名的工程AppWizard。
現(xiàn)在就可以項(xiàng)用MFC AppWizard一樣用這個(gè)定制的向?qū)?。如果不想用?#xff0c;可以在Visual C++ 6.0安裝目錄下Common\MSDev98\Template目錄中刪除該Wizard對(duì)應(yīng)的.awx和.pdb文件。
17. 如何解決Visual C++ 6.0不正確連接的問題
情景:明明改動(dòng)了一個(gè)文件,卻要把整個(gè)項(xiàng)目全部重新編譯鏈接一次。剛剛鏈接好,一運(yùn)行,又提示重新編譯鏈接一次。
這是因?yàn)槌霈F(xiàn)了未來文件(修改時(shí)間和創(chuàng)建時(shí)間比系統(tǒng)時(shí)間晚)的緣故。可以這樣處理:找到工程文件夾下的debug目錄,將創(chuàng)建和修改時(shí)間都比系統(tǒng)時(shí)間的文件全部刪除,然后再從新“Rebuild All
”一次。
18. 引起LNK2001的常見錯(cuò)誤都有哪些
遇到的LNK2001錯(cuò)誤主要為:unresolved external symbol “symbol”
如果鏈接程序不能在所有的庫和目標(biāo)文件內(nèi)找到所引用的函數(shù)、變量或標(biāo)簽,將產(chǎn)生此錯(cuò)誤信息。
一般來說,發(fā)生錯(cuò)誤的原因有兩個(gè):一是所引用的函數(shù)、變量不存在,拼寫不正確或者使用錯(cuò)誤;其次可能使用了不同版本的鏈接庫。以下是可能產(chǎn)生LNK2001錯(cuò)誤的原因:
<1>由于編碼錯(cuò)誤導(dǎo)致的LNK2001錯(cuò)誤
(1)不相匹配的程序代碼或模塊定義(.DEF)文件導(dǎo)致LNK2001。例如,如果在C++源文件了內(nèi)聲明了一變量“var1”,卻試圖在另一個(gè)文件內(nèi)以變量“var1”訪問改變量。
(2)如果使用的內(nèi)聯(lián)函數(shù)是在.cpp文件內(nèi)定義的,而不是在頭文件內(nèi)定義將導(dǎo)致LNK2001錯(cuò)誤。
(3)調(diào)用函數(shù)時(shí)如果所用的參數(shù)類型和頭函數(shù)聲明時(shí)的類型不符將會(huì)產(chǎn)生LNK2001錯(cuò)誤。
(4)試圖從基類的構(gòu)造函數(shù)或析構(gòu)函數(shù)中調(diào)用虛擬函數(shù)時(shí)將會(huì)導(dǎo)致LNK2001錯(cuò)誤。
(5)要注意函數(shù)和變量的可公用性,只有全局變量、函數(shù)是可公用的。靜態(tài)函數(shù)和靜態(tài)變量具有相同的使用范圍限制。當(dāng)試圖從文件外部方位任何沒有在該文件內(nèi)聲明的靜態(tài)變量時(shí)將導(dǎo)致編譯錯(cuò)誤
或LNK2001錯(cuò)誤。
<2>由于編譯和聯(lián)機(jī)的設(shè)置而造成的LNK2001錯(cuò)誤
(1)如果編譯時(shí)使用的是/NOD(/NODERAULTLIB)選項(xiàng),程序所需要的運(yùn)行庫和MFC時(shí)將得到又編譯器寫入目標(biāo)文件模塊,但除非在文件中明確包含這些庫名,否則這些庫不會(huì)被鏈接進(jìn)工程文件。
這種情況下使用/NOD將導(dǎo)致LNK2001錯(cuò)誤
(2)如果沒有為wWinMainCRTStartup設(shè)定程序入口,在使用Unicode和MFC時(shí)將出現(xiàn)“unresolved external on _WinMain@16”的LNK2001錯(cuò)誤信息。
(3)使用/MD選項(xiàng)編譯時(shí),既然所有的運(yùn)行庫都被保留在動(dòng)態(tài)鏈接庫之內(nèi),源文件中對(duì)“func”的引用,在目標(biāo)文件里即對(duì)“__imp__func”的引用。如果試圖使用靜態(tài)庫LIBC.LIB或LIBCMT.LIB進(jìn)
行鏈接,將在__imp__func上發(fā)生LNK2001錯(cuò)誤。如果不使用/MD選項(xiàng)編譯,在使用MSVCxx.LIB鏈接時(shí)也會(huì)發(fā)生LNK2001錯(cuò)誤。
(4)使用/ML選項(xiàng)編譯時(shí),如用LIBCMT.LIB鏈接會(huì)在_errno上發(fā)生LNK2001錯(cuò)誤。
(5)當(dāng)編譯調(diào)試版的應(yīng)用程序時(shí),如果采用發(fā)行版模態(tài)庫進(jìn)行鏈接也會(huì)產(chǎn)生LNK2001錯(cuò)誤;同樣,使用調(diào)試版模態(tài)庫鏈接發(fā)行版應(yīng)用程序時(shí)也會(huì)產(chǎn)生相同的錯(cuò)誤。
(6)不同版本的庫和編譯器的混合使用也能產(chǎn)生問題,因?yàn)樾掳娴膸炖锟赡馨缦鹊陌姹緵]有的符號(hào)和說明。
(7)在不同的模塊中使用內(nèi)聯(lián)和非內(nèi)聯(lián)的編譯選項(xiàng)能夠?qū)е翷NK2001錯(cuò)誤。如果創(chuàng)建C++庫時(shí)打開了函數(shù)內(nèi)聯(lián)(/Ob1或/Ob2),但是在描述該函數(shù)的相應(yīng)頭文件里卻關(guān)閉了函數(shù)內(nèi)聯(lián)(沒有inline關(guān)鍵字
),只是將得到錯(cuò)誤信息。為避免該問題的發(fā)生,應(yīng)該在相應(yīng)的頭文件中用inline關(guān)鍵字標(biāo)志為內(nèi)聯(lián)函數(shù)。
(8)不正確的/SUBSYSTEM或ENTRY設(shè)置也能導(dǎo)致LNK2001錯(cuò)誤。
19. 如何調(diào)試一個(gè)沒有源碼的exe文件調(diào)用的dll
在Visual C++ 6.0中,進(jìn)入“Project Setting”對(duì)話框然后選擇Debug標(biāo)簽頁。通常Visual Studio默認(rèn)“executable for debug session”為可執(zhí)行文件名,但可以將他改成任何你想要的程序。
甚至可以指定不同的工作目錄以及傳遞參數(shù)到你的程序。這個(gè)技術(shù)常用來調(diào)試Dlls、名字空間擴(kuò)展、COM對(duì)象和其他從某些EXE以及從第三方的EXE中調(diào)用的plug-in程序。
20. Visual C++ 6.0工程中的項(xiàng)目文件都表示什么
.opt:工程關(guān)于開發(fā)環(huán)境的參數(shù)文件。如工具條位置等信息。
.aps(AppStudio File)資源輔助文件,二進(jìn)制格式,一般不用去管它。
.clw:ClassWizard信息文件,實(shí)際上是INI文件格式,有興趣可以研究一下。有時(shí)候ClassWizard出了問題,手工修改CLW文件可以解決。如果此文件不存在的話,每次用ClassWizard的時(shí)候回提
示是否重建。
.dsp(DevelopStudio Project):項(xiàng)目文件,文本格式,不過不熟悉的不要手工修改。
.dsw(DevelopStudio Workspace):是工作區(qū)文件,其他特點(diǎn)和.dsp差不多。
.plg:是編譯信息文件,編譯時(shí)的error和warning信息文件(實(shí)際上是一個(gè)html文件),一般用處不大。在單擊菜單【Tool】->【Option】彈出的對(duì)話框里面有個(gè)選項(xiàng)可以控制這個(gè)文件的生成。
.hpj(Help Project):是生成幫助文件的工程,用microsoft Help Compiler可以處理。
.mdp(Microsoft DevStudio Project):是舊版本的項(xiàng)目文件,如果要打開此文件的話,會(huì)提示你是否轉(zhuǎn)換成新的.dsp格式。
.bsc:是用于瀏覽項(xiàng)目信息的,如果用Source Brower的話就必須有這個(gè)文件。如果不用這個(gè)功能的話,可以在Project Options里面去掉Generate Browse Info File,這樣可以加快編譯速度。
.map是執(zhí)行文件的映象信息記錄文件,除非對(duì)系統(tǒng)底層,這個(gè)文件一般用不著。
.pch(Pre-Compiled File):是與編譯文件,可以加快編譯速度,但是文件非常大。
.pdb(Program Database):記錄了程序有關(guān)的一些數(shù)據(jù)和調(diào)試信息,在調(diào)試的時(shí)候可能有用。
.exp:只有在編譯DLL的時(shí)候才會(huì)生成,記錄了DLL文件的一些信息,一般也沒有用。
.ncb:無編譯瀏覽文件(no compile browser)。當(dāng)自動(dòng)完成功能出問題時(shí)可以刪除此文件。編譯工程后會(huì)自動(dòng)生成。
========
vc調(diào)試技巧
http://blog.csdn.net/yaneng/article/details/5660889VC調(diào)試技巧收集整理?
? ? ? 調(diào)試是一個(gè)程序員最基本的技能,其重要性甚至超過學(xué)習(xí)一門語言。不會(huì)調(diào)試的程序員就意味著他即使會(huì)一門語言,卻不能編制出任何好的軟件。
? ? ? 這里我簡(jiǎn)要的根據(jù)自己的經(jīng)驗(yàn)列出調(diào)試中比較常用的技巧,希望對(duì)大家有用。本文約定,在選擇菜單時(shí),通過/表示分級(jí)菜單,例如File/Open表示頂級(jí)菜單File的子菜單open。 ? ? ?
? ? ?
? ? ? 1 設(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)行:?
? ? ?
? ? ? a 打開Project settings對(duì)話框(可以通過快捷鍵ALT+F7打開,也可以通過IDE菜單Project/Settings打開)?
? ? ?
? ? ? b 選擇C/C++頁,Category中選擇general ,則出現(xiàn)一個(gè)Debug Info下拉列表框,可供選擇的調(diào)試信息方式包括:?
? ? ? None:
? ? ? 沒有調(diào)試信息?
? ? ? Line Numbers Only:
? ? ? 目標(biāo)文件或者可執(zhí)行文件中只包含全局和導(dǎo)出符號(hào)以及代碼行信息,不包含符號(hào)調(diào)試信息?
? ? ? C7 Compatible:?
? ? ? 目標(biāo)文件或者可執(zhí)行文件中包含行號(hào)和所有符號(hào)調(diào)試信息,包括變量名及類型.函數(shù)及原型 等?
? ? ? Program Database:?
? ? ? 創(chuàng)建一個(gè)程序庫(PDB),包括類型信息和符號(hào)調(diào)試信息。?
? ? ? Program Database for Edit and Continue:?
? ? ? 除了上面的功能外,這個(gè)選項(xiàng)允許對(duì)代碼進(jìn)行調(diào)試過程中的修改和繼續(xù)執(zhí)行。
? ? ? 這個(gè)選項(xiàng)同時(shí)使#pragma設(shè)置的優(yōu)化功能無效?
? ? ?
? ? ? c 選擇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ǔ)上被編譯(即增量編譯),而不必每次都從頭開始編譯。?
?
? ? ? 2 斷點(diǎn)
? ? ? 斷點(diǎn)是調(diào)試器設(shè)置的一個(gè)代碼位置。當(dāng)程序運(yùn)行到斷點(diǎn)時(shí),程序中斷執(zhí)行,回到調(diào)試器。斷點(diǎn)是?
? ? ? 最常用的技巧。調(diào)試時(shí),只有設(shè)置了斷點(diǎn)并使程序回到調(diào)試器,才能對(duì)程序進(jìn)行在線調(diào)試。
? ? ?
? ? ? 設(shè)置斷點(diǎn):可以通過下述方法設(shè)置一個(gè)斷點(diǎn)。首先把光標(biāo)移動(dòng)到需要設(shè)置斷點(diǎn)的代碼行上,然后?
? ? ? 按F9快捷鍵?
? ? ? 彈出Breakpoints對(duì)話框,方法是按快捷鍵CTRL+B或ALT+F9,或者通過菜單Edit/Breakpoints打開。打開后點(diǎn)擊Break?
? ? ? at編輯框的右側(cè)的箭頭,選擇 合適的位置信息。一般情況下,直接選擇line?
? ? ? xxx就足夠了,如果想設(shè)置不是當(dāng)前位置的斷點(diǎn),可以選擇Advanced,然后填寫函數(shù)、行號(hào)和可執(zhí)行文件信息。
? ? ? 去掉斷點(diǎn):把光標(biāo)移動(dòng)到給定斷點(diǎn)所在的行,再次按F9就可以取消斷點(diǎn)。同前面所述,打開Breakpoints對(duì)話框后,也可以按照界面提示去掉斷點(diǎn)。
? ? ?
? ? ? 條件斷點(diǎn):可以為斷點(diǎn)設(shè)置一個(gè)條件,這樣的斷點(diǎn)稱為條件斷點(diǎn)。對(duì)于新加的斷點(diǎn),可以單擊Conditions按鈕,為斷點(diǎn)設(shè)置一個(gè)表達(dá)式。當(dāng)這個(gè)表達(dá)式發(fā)生改變時(shí),程序就?
? ? ? 被中斷。底下設(shè)置包括“觀察數(shù)組或者結(jié)構(gòu)的元素個(gè)數(shù)”,似乎可以設(shè)置一個(gè)指針?biāo)赶虻膬?nèi)存區(qū)的大小,但是我設(shè)置一個(gè)比較的值但是改動(dòng)?
? ? ? 范圍之外的內(nèi)存區(qū)似乎也導(dǎo)致斷點(diǎn)起效。最后一個(gè)設(shè)置可以讓程序先執(zhí)行多少次然后才到達(dá)斷點(diǎn)。
? ? ?
? ? ? 數(shù)據(jù)斷點(diǎn):數(shù)據(jù)斷點(diǎn)只能在Breakpoints對(duì)話框中設(shè)置。選擇“Data”頁,就顯示了設(shè)置數(shù)據(jù)斷點(diǎn)的對(duì)話框。在編輯框中輸入一個(gè)表達(dá)式,當(dāng)這個(gè)?
? ? ? 表達(dá)式的值發(fā)生變化時(shí),數(shù)據(jù)斷點(diǎn)就到達(dá)。一般情況下,這個(gè)表達(dá)式應(yīng)該由運(yùn)算符和全局變量構(gòu)成,例如:在編輯框中輸入?
? ? ? g_bFlag這個(gè)全局變量的名字,那么當(dāng)程序中有g(shù)_bFlag= !g_bFlag時(shí),程序就將停在這個(gè)語句處。
? ? ?
? ? ? 消息斷點(diǎn):VC也支持對(duì)Windows消息進(jìn)行截獲。他有兩種方式進(jìn)行截獲:窗口消息處理函數(shù)和特定消息中斷。在Breakpoints對(duì)話框中選擇Messages頁,就可以設(shè)置消息斷點(diǎn)。如果在上面那
個(gè)對(duì)話框中寫入消息處理函數(shù)的名字,那么?
? ? ? 每次消息被這個(gè)函數(shù)處理,斷點(diǎn)就到達(dá)(我覺得如果采用普通斷點(diǎn)在這個(gè)函數(shù)中截獲,效果應(yīng)該一樣)。如果在底下的下拉?
? ? ? 列表框選擇一個(gè)消息,則每次這種消息到達(dá),程序就中斷。
? ? ? 3 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)致 軟件的邏輯被破壞。
? ? ? 4 Memory
? ? ? 由于指針指向的數(shù)組,Watch只能顯示第一個(gè)元素的值。為了顯示數(shù)組的后續(xù)內(nèi)容,或者要顯示一片內(nèi)存的內(nèi)容,可以使用memory功能。在?
? ? ? Debug工具條上點(diǎn)memory按鈕,就彈出一個(gè)對(duì)話框,在其中輸入地址,就可以顯示該地址指向的內(nèi)存的內(nèi)容。
?
? ? ? 5 Varibles
? ? ? Debug工具條上的Varibles按鈕彈出一個(gè)框,顯示所有當(dāng)前執(zhí)行上下文中可見的變量的值。特別是當(dāng)前指令涉及的變量,以紅色顯示。
? ? ? 6 寄存器
? ? ? Debug工具條上的Reigsters按鈕彈出一個(gè)框,顯示當(dāng)前的所有寄存器的值。
? ? ? 7 進(jìn)程控制
? ? ? VC允許被中斷的程序繼續(xù)運(yùn)行、單步運(yùn)行和運(yùn)行到指定光標(biāo)處,分別對(duì)應(yīng)快捷鍵F5、F10/F11和CTRL+F10。各個(gè)快捷鍵功能如下:?
? ? ? 快捷鍵 說明?
? ? ? F5 繼續(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)處。?
?
? ? ? 8 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ù)中去。
? ? ? 9 其他調(diào)試手段
? ? ? 系統(tǒng)提供一系列特殊的函數(shù)或者宏來處理Debug版本相關(guān)的信息,如下:?
? ? ?
? ? ? 10 宏名/函數(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á)式的值。?
? ? ?
? ? ? 關(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ù)編譯頭。
? ? ? [url]http://www.yzcc.com/yzcc/vv/08475592434.html[/url]
? ? ? 其他技巧:
? ? ? 1.在調(diào)試狀態(tài)下怎樣查看錯(cuò)誤消息(GetLastError())?
? ? ? 通??梢杂肎etLastError()得到錯(cuò)誤編號(hào)然后用FormatMessage(...)得到錯(cuò)誤描述。
? ? ? 這里有一個(gè)更直接的辦法:在Watch窗口添加@err,hr
? ? ? 2.怎樣知道程序是否有內(nèi)存泄漏(Memory Leak)?
? ? ? 在VC開發(fā)環(huán)境下Press?
? ? ? [F5],在調(diào)試狀態(tài)下運(yùn)行程序,測(cè)試有可能出現(xiàn)內(nèi)存泄漏的操作,關(guān)閉程序,在Output窗口查看運(yùn)行信息.如果出現(xiàn)泄漏,在Output中會(huì)有記錄。當(dāng)然,不能完全依靠這種方式來發(fā)現(xiàn)程序運(yùn)行有內(nèi)存泄漏。
? ? ? 3.當(dāng)某一變量滿足某種條件時(shí),停止在斷點(diǎn).
? ? ? 如以下一程序片段:
? ? ? 2 int iLocation;
? ? ? ...
? ? ? 30 iLocation++
? ? ? ...
? ? ? 要求: 在line30設(shè)有斷點(diǎn),并想在iLocation>100?
? ? ? 本文來源:[url]http://blog.tianya.cn/blogger/post_show.asp?BlogID=237133&PostID=3587659[/url]
便于調(diào)試的代碼風(fēng)格:
不用全局變量
所有變量都要初始化,成員變量在構(gòu)造函數(shù)中初始化
盡量使用const
詳盡的注釋
VC++編譯選項(xiàng):
總是使用/W4警告級(jí)別
在調(diào)試版本里總是使用/GZ編譯選項(xiàng),用來發(fā)現(xiàn)在Release版本中才有的錯(cuò)誤
沒有警告的編譯:保證在編譯后沒有任何警告,但是在消除警告前要進(jìn)行仔細(xì)檢查
調(diào)試方法:
1、使用 Assert(原則:盡量簡(jiǎn)單)
assert只在debug下生效,release下不會(huì)被編譯。
例子:
char* strcpy(char* dest,char* source)
{
assert(source!=0);
assert(dest!=0);
char* returnstring = dest;
while((*dest++ = *source++)!= ‘/0’)
{
;
}
return returnstring;
}?
2、防御性的編程
例子:
char* strcpy(char* dest,char* source)
{
if(source == 0)
{
assert(false);
reutrn 0;
}
if(dest == 0)
{
assert(false);
return 0;
}
char* returnstring = dest;
while((*dest++ = *source++)!= ‘/0’)
{
;
}
return returnstring;
}?
3、使用Trace
以下的例子只能在debug中顯示,
例子:
a)、TRACECString csTest = “test”;
TRACE(“CString is %s/n”,csTest);
b)、ATLTRACE
c)、afxDump
CTime time = CTime::GetCurrentTime();
#ifdef _DEBUG
afxDump << time << “/n”;
#endif
4、用GetLastError來檢測(cè)返回值,通過得到錯(cuò)誤代碼來分析錯(cuò)誤原因
5、把錯(cuò)誤信息記錄到文件中
異常處理
程序設(shè)計(jì)時(shí)一定要考慮到異常如何處理,當(dāng)錯(cuò)誤發(fā)生后,不應(yīng)簡(jiǎn)單的報(bào)告錯(cuò)誤并退出程序,應(yīng)當(dāng)盡可能的想辦法恢復(fù)到出錯(cuò)前的狀態(tài)或者讓程序從頭開始運(yùn)行,并且對(duì)于某些錯(cuò)誤,應(yīng)該能夠容錯(cuò),即允
許錯(cuò)誤的存在,但是程序還是能夠正常完成任務(wù)。
調(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í)停下來。
常見錯(cuò)誤
1、在函數(shù)返回的時(shí)候程序崩潰的原因
a)、寫自動(dòng)變量越界
b)、函數(shù)原型不匹配
2、MFC
a)、使用錯(cuò)誤的函數(shù)原型處理用戶定義消息
正確的函數(shù)原型為:
afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);
3、謹(jǐn)慎使用TerminateThread:使用TerminateThread會(huì)造成資源泄漏,不到萬不得已,不要使用。
4、使用_beginthreadex,不要使用Create Thread來常見線程。
WindowS 調(diào)試
1.Windows跟蹤語句:
(1)TRACE(_T(“Warning (FunctionName):Object %s not found./n”),objectName);
在輸出的調(diào)試窗口會(huì)輸出結(jié)果。跟蹤信息輸出到輸出窗口output window中。[調(diào)試版本中使用]
(2)C++的C運(yùn)行時(shí)刻庫函數(shù)跟蹤語句
? ? ANSI C 運(yùn)行時(shí)刻庫函數(shù)沒有跟蹤語句,但是VC++的C運(yùn)行時(shí)刻庫函數(shù)有??墒褂胈RPTn或_RPTFn調(diào)試報(bào)告宏,但是你必須在程序中引用crtdbg.h,并利用C運(yùn)行時(shí)刻函數(shù)庫鏈接:
? ?_RPT0(reportType,format);
? ?_RPT1(reportType,format,arg1);
? ?_RPT2(reportType,format,arg1,arg2);
? ?_RPTF0(reportType,format);
? ?_RPTF1(reportType,format,arg1);
? ?_RPTF2(reportType,format,arg1,arg2);
? ?例子:
? ? ? ? ? int a =1000,b=2000;
? ? ? ? ?int *p =&a;
? ? ? ? ?int *q = &b;
? ? ? ?_RPTF2(_CRT_WARN,"%x ,%x",p,q); //直接在outputwindow中輸出
? ? ? ?_RPTF2(_CRT_ERROR,"%x ,%x",p,q); ? //彈出ERROR對(duì)話框
? ? ? ?_RPTF2( _CRT_ASSERT,"%x ,%x",p,q); ? //彈出AEESRT對(duì)話框
reportType:_CRT_WARN _CRT_ERROR _CRT_ASSERT
其中_CRT_WARN用于跟蹤語句,_RPTFn宏報(bào)告了源碼文件名和調(diào)用這些宏的行號(hào)。[調(diào)試版本中使用]
可以使用_CrtSetReportMode函數(shù)改變默認(rèn)輸出設(shè)置,(比如輸出到調(diào)試器輸出窗口,文件,消息框中),_CrtSetReportFile可以指定將報(bào)告輸出到哪個(gè)文件中。
(3)MFC中的跟蹤語句
? ? ? ?區(qū)別:使用TRACE宏時(shí),需要使用_T宏來格式化參數(shù)以正確解決Unicode的校正,反之,在TRACEn類型的宏中,不必使用_T宏。
? ? ? ?TRACE(_T("ssss/n"));
? ? ? ?TRACE2("%d r %d l/n",1,2);
(4)異常和返回值
C++程序中可以使用異常和返回值來返回狀態(tài)信息。C語言返回一個(gè)函數(shù)的狀態(tài)的最好方法就是它的返回值
Try
{
//code may fail
}
Catch
{
//handle the failure
}
只有在拋出異常的時(shí)候會(huì)有開銷!Catch塊有一些開銷,但是try塊有很少的開銷!只能在調(diào)試版中處理異常,并彈出MessageBox,發(fā)布版不處理異常,為的就是優(yōu)化。
? ? ?try
? ? ?{
? ? ? ?int *pInt = 0;
? ? ? ?*pInt =42;
? ? ?}
? ? ?catch(...)
? ? ?{
? ? ? ?MessageBox(_T("Exception was caught!"),_T("Exception test"),MB_OK); ??
? ? ?}
? ? ? (5)ANSI C++ 運(yùn)行時(shí)刻函數(shù)庫跟蹤
具體有:C語言的stderr和C++語言的clog流,在Windows程序中沒有任何效果!
(6)OutputDebugString (_T(“trace ? debug info!/n”));[調(diào)試版本中使用]
? ? ? ?如果只想在調(diào)試版本中使用OutputDebugString,可以使用下面得宏來實(shí)現(xiàn):
#ifdef ? _DEBUG
#define OutputTraceString(text) ? OutputDebugString(text)
#else
#define OutputTraceString(text) ? ((void) (0))
#endif
使用AfxOutputDebugString
AfxOutputDebugString宏使用和OutputDebugString一樣的語法。
7.使用CObiect::Dump
CObject類有一個(gè)轉(zhuǎn)儲(chǔ)(dump)虛擬函數(shù),繼承于它的所有子類函數(shù)都可以重載這個(gè)函數(shù),輸出它們的值。
例 1 -2:用下列語句輸出CObject派生類pObject的值。afxDump是預(yù)定義的全局變量CDumpContext,注意 CDumpContext對(duì)最一般的內(nèi)建數(shù)據(jù)類型及CObject的指針和引用支持插入操作符(<<)
。有幾個(gè)CObject派生的類也有定 義的插入操作符,CPoint,CSize,CRect,CString,CTime和CTimeSpan。
#if _DEBUG
AfxDump(pObiect);
pObject->Dump(afxDump);
afxDump<<pObject;
#endif
例1-3:
afxDump<<_T(“Warning:This object doesn’t seem right:/n”)<<pObject;
8.使用AfxDump
AfxDump是MFC中相當(dāng)于cerr流的跟蹤語句,所以你可以直接向它輸出跟蹤消息。
TRACE宏由afxDump實(shí)現(xiàn),afxDump由AfxOutputDebugString實(shí)現(xiàn)。而AfxOutputDebugString在調(diào)試版中由_RPT0宏實(shí)現(xiàn)??梢允褂孟旅娴姆椒▽fxDump重定向。
#ifdef _DEBUG
CFile dumpFile; //必須為全局變量
? ? ?dumpFile.Open(_T("dump.log"),CFile::modeWrite|CFile::modeCreate);
? ? ?afxDump.m_pFile = &dumpFile;
#endif
9.使用AfxDumpStack
可以使用AfxDumpStack函數(shù)輸出一個(gè)調(diào)用棧:
void AFXAPI AfxDumpStack(DWORD dwTarget = AFX_STACK_DUMP_TARGET_DEFAULT);
參 數(shù):dwTarget決定在調(diào)試和發(fā)布版本中輸出到什么地方,可以輸出到TRACE宏,OutputDebugString或到剪貼板。如果使用 AFX_STACK_DUMP_TARGET_TRACE,含義是在調(diào)試版中輸出到
TRACE宏,而在發(fā)布版本中沒有輸出!如果你希望在發(fā)布版本中輸出, 可使用AFX_STACK_DUMP_TARGET_ODS選項(xiàng),而且必須在路徑中有Imagehlp.dll文件。在project&?
#61664;settingsLinkCategoryDebug Both formats。?
10.ATL跟蹤語句 最基本的類型是AtlTrace函數(shù):
inline void_cdecl AtlTrace(LPCTSTR format……);
ATLTRACE (format……);
和MFC TRACE宏一樣,它使用一個(gè)512字節(jié)固定大小的緩沖區(qū),如果它的參數(shù)需要一個(gè)大于512字節(jié)的文本緩沖區(qū),會(huì)導(dǎo)致一個(gè)出錯(cuò)的斷言。實(shí)際上,它是使用API函數(shù)OutputDebugString實(shí)現(xiàn)的,
因此它的輸出不能改變到其他目標(biāo)。
ATL跟蹤語句的另一個(gè)選擇AtlTrace2函數(shù):
Inline void _cedecl AtlTrace2(DWORD category,UINT level,LPCTSTR format,…);
ATLTRACE(category,level,format);
該 函數(shù)增加了一個(gè)參數(shù)跟蹤類別(category)(例如,atlTraceCOM,atlTraceWindowing和 atlTraceControl)和一個(gè)參數(shù)嚴(yán)格級(jí)別。類別值是位掩碼,ATL自身使用介于0-2的級(jí)別值,0級(jí)指最嚴(yán)格的級(jí)別
。 和AtlTrace函數(shù)類似,AtlTrace2函數(shù)只能用在調(diào)試版本中!
11.VC++消息Pragma
Pagama是一個(gè)編譯時(shí)的跟蹤語句,可用來警告在預(yù)處理過程中發(fā)現(xiàn)的潛在的編連(build)問題
12.處理長字符串:[例如處理SQL語句]
(1)MFC下[只能調(diào)試版]
TRACE(longString); //assert if _tcslen(longString)>511,最大是512
#ifdef _DEBUG
afxDump<<longString;//dosen’t assert for long strings 不需要判斷
#endif
(2)ATL下[只能調(diào)試版]
ATLTRACE(longString); //assert if _tcslen(longString)>511,最大是512
#ifdef _DEBUG
OutputDebugString(longString); //dosen’t assert for long strings 不需要判斷
#endif
13.處理大量的跟蹤輸出。
如果跟蹤消息數(shù)據(jù)產(chǎn)生的速度超過輸出窗口處理的速度,那么消息會(huì)塞滿緩沖區(qū),數(shù)據(jù)會(huì)丟失。
簡(jiǎn)單方法:在輸出大量數(shù)據(jù)的代碼段,例如對(duì)象轉(zhuǎn)儲(chǔ)函數(shù)時(shí)候,調(diào)用 Sleep API函數(shù)。例如:Sleep(100).
?調(diào)試
1.當(dāng)錯(cuò)誤發(fā)生得時(shí)候,調(diào)用GetLastError()得到相應(yīng)得錯(cuò)誤碼
錯(cuò)誤碼得位域有固定的格式,,在C:/Program Files/Microsoft Visual Studio/VC98/Include/Winerror.h中有詳細(xì)的說明:
//
// ? Values are 32 bit values layed out as follows:
//
// ? 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// ? 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// ? +---+-+-+-----------------------+-------------------------------+
// ? |Sev|C|R| ? ? Facility ? ? ? ? ? | ? ? ? ? ? ? ? Code ? ? ? ? ? ? |
// ? +---+-+-+-----------------------+-------------------------------+
//
// ? ? ? Sev - is the severity code ? ? ? 安全代碼
//
// ? ? ? ? ? 00 – Success ? ? ? ? ? 0-安全 ??
// ? ? ? ? ? 01 – Informational ? ? 1-信息
// ? ? ? ? ? 10 – Warning ? ? ? ? 2-警告
// ? ? ? ? ? 11 – Error ? ? ? ? ? ? 3-錯(cuò)誤
// ? ? ? C - is the Customer code flag?
客戶代碼:0-Microsoft定義的,1-客戶定義的
// ? ? ? R - is a reserved bit 保留位必須是0 ?
// ? ? ? Facility - is the facility code工具-Microsoft 定義的
// ? ? ? Code - is the facility's status code 工具狀態(tài)代碼-Microsoft或客戶定義
? ?工具:更好的查看錯(cuò)誤代碼的方法,Tools-》Error Lookup;在VC++調(diào)試器的watch窗口中輸入@ERR監(jiān)視GetLastError的返回?cái)?shù)值,ERR是調(diào)試器用來顯示最新錯(cuò)誤碼的一個(gè)虛擬寄 存器。還可
以用 @ERR,hr將錯(cuò)誤碼轉(zhuǎn)換為文本格式
? ?
? ?技巧:在調(diào)試中,按F11鍵,Alt+8顯示反匯編窗口,在Edit菜單中選擇Go To命令,在GoTo對(duì)話框的Go to what中選擇Address選項(xiàng),在Enter address expression中輸入導(dǎo)致崩潰的地址。
創(chuàng) 建映射文件的方法:ProjectSettingsLinkGenerate mapfile.即可在工程的Debug文件下看到。映射文件里面所有的公共符號(hào)都使用混合名字??墒褂肰C++的名字
解析工具(Undname)將混合 名字轉(zhuǎn)換到原始名字。你可以在“開始””運(yùn)行””cmd”輸入
C:/Documents and Settings/zhangzhongping>cd C:/Program Files/Microsoft Visual Studio/Common/Tools
輸入:
C:/ProgramFiles/MicrosoftVisualStudio/Common/Tools>Undname ?RandException@@YGXHHHH@Z
Microsoft(R) Windows NT(R) Operating System
UNDNAME Version 5.00.1768.1Copyright (C) Microsoft Corp. 1981-1998
輸出:
>> ?RandException@@YGXHHHH@Z == RandException
當(dāng)輸入-f時(shí),顯示整個(gè)函數(shù)的原型!查看映射文件的時(shí)候,若出現(xiàn)重載函數(shù),名字解析工具很有用!
輸入:
C:/ProgramFiles/MicrosoftVisualStudio/Common/Tools>Undname-f ?RandException@@YGXHHHH@Z
Microsoft(R) Windows NT(R) Operating System
UNDNAME Version 5.00.1768.1Copyright (C) Microsoft Corp. 1981-1998
輸出:
>> ?RandException@@YGXHHHH@Z == void __stdcall RandException(int,int,int,int)
使用MFC和ATL的DEF文件:
MFC的DEF文件在
C:/ProgramFiles/MicrosoftVisual Studio/VC98/MFC/SRC/Intel目錄下。
ATL的DEF文件在
C:/Program Files/Microsoft Visual Studio/VC98/ATL/SRC目錄下。
如 果用戶運(yùn)行自己的程序出現(xiàn):The ordinal 6880 could not be located in the dynamic link Library MFC42.dll信息。你可查看MFC42.DEF中對(duì)應(yīng)的6880號(hào)函數(shù):??
ScreenToClient@CWnd@@QBEXPAUtagRECT@@@Z @ 6880 NONAME.然后可以用名字解析工具解析混合名字如下:
輸入:
C:/Program Files/Microsoft Visual Studio/Common/Tools>Undname -f ?ScreenToClient@CWnd@@QBEXPAUtagRECT@@@Z @ 6880 NONAME
Microsoft(R) Windows NT(R) Operating System
UNDNAME Version 5.00.1768.1Copyright (C) Microsoft Corp. 1981-1998
輸出:
>> ?ScreenToClient@CWnd@@QBEXPAUtagRECT@@@Z == public: void __thiscall CWnd::ScreenToClient(struct tagRECT *)const
>> @ == @
>> 6880 == 6880
>> NONAME == NONAME
使用依賴關(guān)系瀏覽工具:
VC++依賴關(guān)系瀏覽工具(COMMON/TOOLS/Depends.exe)
?內(nèi)存泄漏的調(diào)試
在VC中我們使用_CrtDumpMemoryLeaks()來檢測(cè)內(nèi)存泄漏。
例子:
void CTRACEDlg::OnButton1()?
{
? ? ?int *pLeak = new int; //故意造成內(nèi)存泄漏
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
? ? ?//delete pLeak;
? ? ?//pLeak = NULL;
? ? ?_CrtDumpMemoryLeaks();//調(diào)用此函數(shù)在output window的Debug窗口中顯示內(nèi)存泄漏的地址的數(shù)據(jù)。
? ??
}
Debug窗口中顯示:
Detected memory leaks!
Dumping objects ->
C:/ProgramFiles/MicrosoftVisualStudio/MyProjects/TRACE/TRACEDlg.cpp(181) : {89} normal block at 0x004213B0, 4 bytes long.
Data: < ? ? > CD CD CD CD?
Object dump complete.
注意:0xCD表示已經(jīng)分配的數(shù)據(jù)
? ? ? ?0xDD表示已經(jīng)釋放的數(shù)據(jù)
? ? ? ?0xFD表示被保護(hù)的數(shù)據(jù)
斷言
1.斷言的特征:
(1)發(fā)現(xiàn)運(yùn)行時(shí)刻錯(cuò)誤(用戶輸入錯(cuò)誤,資源分配錯(cuò)誤,文件系統(tǒng)錯(cuò)誤,硬件錯(cuò)誤或其他類型錯(cuò)誤)
(2)斷言中的布爾表達(dá)式顯示的是某個(gè)對(duì)象或者狀態(tài)的有效性,而不是正確性
(3)斷言在條件編譯后只存在調(diào)試版本里面,特別是,斷言只在_DEBUG符號(hào)定義后,才能編譯!
(4)斷言不能包含程序代碼,也不能有副作用,不能修改程序變量,也比能調(diào)用修改程序變量的函數(shù)
(5)斷言只是給程序員提供有用信息的
2.斷言的類型
(1)ANSI C斷言
Void assert(expression) ? ? 包含在assert.h頭文件中(最好不用assert)
原因:*當(dāng)文件名太長的化,對(duì)話框顯示的路徑將會(huì)被截至掉!
*函數(shù)是由ANSI NDEBUG函數(shù)驅(qū)動(dòng)的,如果定義了NDEBUG后,斷言就被取消!
如果要啟用JIT調(diào)試(Just-in-time),在ToolsOptionsDebug
中選擇Just-in-time debugging,默認(rèn)也會(huì)勾選上OLE RPC debugging
單擊“重試(R)”就會(huì)顯示出錯(cuò)誤所在的標(biāo)記行。
(2)C運(yùn)行時(shí)刻函數(shù)庫斷言
_ASSERT(Boolean Expression) ? (crtdbg.h)[不用]
_ASSERTE(Boolean Expression) ? (crtdbg.h)[經(jīng)常用這個(gè)]
_ASSERTE宏更能給出更多簡(jiǎn)潔,有用的信息,顯示了斷言!
(3)MFC庫中的斷言
ASSERT(Boolean expression) ASSERT宏和_ASSERT宏顯示的消息框相同。VERIFY(Boolean expression) VERIFY 中的BOOL表達(dá)式在發(fā)布版本中被保留了下來。它簡(jiǎn)化了對(duì)返回值的判斷!
CString str;
VERIFY(str.LoadString(IDS_STRING));//不要用VERIFY宏
ASSERT_VALID宏,被用來決定一個(gè)指向CObject派生類的對(duì)象的指針是否有效。ASSERT(pObjectDerivedFromCObject);主要是在使用CObject派生類對(duì)象之前調(diào)用,檢查對(duì)象的有效性。
ASSERT_KINDOF(className,pObjectDerivedFromCObject);
ASSERT_POINTER(pointer,pointerType);
ASSERT_NULL_OR_POINTER(pointer,pointerType);
AfxlsValidAddress(const void*memoryAddress,UINT memoryBytes,BOOL isWriteable = TRUE);
BOOL AfxlsValidString (LPCSTR string, int stringLength = -1);
(4)ATL斷言
如果你使用ATL,crtdbg.h就包含在atlbase.h中。在任何ATL代碼中,ATLASSERT才是你的選擇,在atldef.h中你會(huì)發(fā)現(xiàn)ATLASSERT是_ASSERT的一個(gè)別名。
優(yōu)點(diǎn):在ATL程序中使用ATLASSERT可以讓你使用自己的斷言。
(5)考慮使用_ASSERTE(FALSE)來簡(jiǎn)化防御性的編程和斷言的結(jié)合,要想得到描述性的斷言消息,考慮使用_ASSERTE(“Problem description.”==0).
_ASSERTE("This is the object requires the MM_TEXT mapping mode" == 0);
If (!expression)
{
//handle error
_ASSERT(FALSE);
…
}
If(FAILED(SomeFunction()))
{
//handle error
_ASSERT(FALSE)
}
(6)考慮使用_CrtSetReportMode和_CrtSetReportFile
========
總結(jié)
以上是生活随笔為你收集整理的VC++调试技巧学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++单元测试学习总结9
- 下一篇: VC++ 自定义消息学习总结