VC項目調試基礎

來源:互聯網
上載者:User

一.Debug版本和Release版本的區別

Debug通常稱為調試版本,它包含調試資訊,並且不作任何最佳化,便於程式員偵錯工具。Release稱為發布版本,它往往是進行了各種最佳化,使得程式在代碼大小和運行速度上都是最優的,以便使用者很好地使用。

只有Debug版本的程式才能設定斷點、逐步執行、使用TRACE/ASSERT等調試輸出語句。Release版本不包含任何調試資訊,所以體積小、運行速度快。

一般而言Debug版本會比Release版本多出*.ilk檔案和*.pdb檔案。

1.*.ilk檔案

ilk尾碼全稱為“Incremental Linking”,意即增量連結。

VC6中,“Project Setting->Link(Category:General)”預設勾選“Link incrementally”;相應VC2005中,“項目屬性->配置屬性->連結器->常規->啟用增量連結”預設選項為“是(/INCREMENTAL)”。

當選定漸增型編譯連結時,連結器自動產生ILK檔案,記錄連結資訊,也就是每次重新編譯並不編譯所有的源檔案,只編譯改動過的檔案。而編譯器怎麼知道哪些編譯過哪些未編譯過呢,除了檢查修改時間外,這個ilk檔案也是很重要的資訊。

在VS2005中,斷點變成了驚嘆號圓圈,若提示“當前不會命中斷點。此位置當前尚未載入可執行代碼”,則可能是沒有開啟產生調試資訊的/Zi開關。在“項目屬性->配置屬性->C/C++->常規->調試資訊格式”處選擇“程式資料庫(/Zi)”。在“項目屬性->配置屬性->連結器->調試->產生調試資訊” 處選擇“是(/DEBUG) ”。若提示“當前不會命中斷點,原始碼與原始版本不同。”,嘗試將“工具->選項->調試”中“要求源檔案與原始版本完成匹配”前的勾去掉,刪除Debug目錄重建解決方案。

/C7

C 7.0- Compatible

目標檔案或者可執行檔中包含行號和所有符號調試資訊,包括變數名及類型,函數及原型等

/Zi

Program Database

建立一個程式庫(PDB),包括類型資訊和符號調試資訊。

某個源檔案中設定的斷點老是無效,提示“當前不會命中斷點。原始碼與原始版本不同”資訊,清理項目、重編項目、重新拷貝原檔案都解決不了問題。“工具->選項->調試”去掉“要求源檔案與原始版本完成匹配”前面的勾。

參考: 《VS2005 當前不會命中斷點,還沒有為該文檔載入任何符號》

2.*.pdb檔案

pdb尾碼全稱為“Program Debug Database”,意即程式資料庫檔案。

VC6中,“Project Setting->Link (Category:General)”預設勾選“Generate debug info”,“Project Setting->Link (Category:Customize)”預設勾選“Use program database”;相應VC2005中,“項目屬性->配置屬性->連結器->調試”,預設“產生調試資訊”選項為“是(/DEBUG)”,預設“產生程式資料庫檔案”處填寫“.\Debug\*.pdb”。該選項對應的編譯開關為/PDB。

符號檔案(Symbol Files)是一個資料資訊檔,它包含了應用程式二進位檔案(比如EXE、DLL等)的調試資訊,專門用來作調試之用,最終產生的可執行檔在運行時並不需要這個符號檔案,但你的程式中所有的變數資訊都記錄在這個檔案中。所以調試應用程式時,這個檔案是非常重要的。用VC和 WinDbg偵錯工具時都要用到這個檔案。

關於符號檔案,參考《PDB Files(C++)》《符號檔案—Windows
應用程式調試必備》。

 

二.VC常用調試操作

快速鍵

作用

F5

開始調試,逐斷點調試

F9

設定(取消)斷點

Ctrl+F10

調試到游標所在位置

F10

單步調試,遇到子函數跳過

F11

單步調試,遇到子函數跟蹤進入內部

Shift+F11

從當前函數中跳出

Shift+F5

停止調試

一般F9設斷點,F5啟動後,F10、F11和Shift+F11交替使用,以在多個斷點處調試。

 

三.源碼跟蹤調試

我們在VC2005中printf函數調用處設定斷點,F11 將開啟printf函數的源碼檔案C:\ProgramFiles\Microsoft Visual Studio 8\VC\crt\src\printf.c進入printf函數內部,實際上“工具->選項->項目和解決方案->VC++目錄->源檔案”中包含了crt原始碼的路徑:$(VCInstallDir)crt\src。

而在VC6中,C:\ProgramFiles\Microsoft Visual Studio\VC98\CRT\SRC不存在,故試圖F11進入printf內部時,將彈出“Find Source”對話方塊,提示“Please enter the path for PRINTF.C”檔案。

調試VC時,編譯器之所以能夠跟蹤進入C庫函數,是因為編譯器本身附帶提供了Debug版本的CRT庫。

VC6中的MSVCRTD.DLL-MSVCRTD.LIB-MSVCRTD.PDB(對應VC2005中msvcr80d.dll-msvcrtd.lib)為C Runtime Library的Debug版本,其中包含了C運行庫的調試資訊。

VC6中的MSVCP60D.DLL-MSVCPRTD.LIB-MSVCP60D.PDB(對應VC2005中msvcp80d.dll- msvcprtd.lib)為C++Runtime Library的Debug版本,其中包含了C++運行庫的調試資訊。

鑒於Debug版本對調試資訊的記錄和Dll->Lib(*.obj,*.lib)->Src(*.c,*.cpp)的對應關係,在VC中我們就可以設定斷點跟蹤調試代碼。

 

四.反組譯碼

在VC2005中,“檔案屬性->C/C++->輸出檔案->彙編輸出”預設為“無列表”,可選項如下:

(1)“僅列出程式集(/FA)”:產生FA.asm,有行號無原始碼。

(2)“帶原始碼的程式集(/FAs)”:產生FAs.asm,有行號和原始碼。

(3)“帶機器碼的程式集(/FAc)”:產生FAc.cod,在FA.asm基礎上列出了機器碼。

(4) “程式集、機器碼和原始碼(/FAcs)”:產生FAcs.cod,在FAc.cod的基礎上列出了對應的原始碼。

在Debug狀態下,“調試->視窗->反組譯碼(Alt+8)”,其中“Alt+8” 反組譯碼顯示的即為/FAs結果。在調試過程中,可“Alt+5”呼出寄存器視窗,查看資料寄存器(EAX/EBX/ECX/EDX)、變址寄存器(ESI/EDI)、控制寄存器(EFL/EIP)和指標寄存器(ESP/EBP)的即時狀態值。

可在命令視窗中輸入 “cl /?”查看協助中的“-OUTPUT FILES-”部分的說明。詳情可參考MSDN中的說明:《/FA, /Fa (ListingFile)》《/FA、/Fa(列表檔案)》。

 

五.連結庫(lib、dll)項目和應用程式(exe)項目聯合調試

對於連結庫項目,必須要匯入一個能夠調用它的測試程式進來,通過應用程式的執行來達到調試的目的。

既然是調試,當然靜態或動態連結程式庫項目應產生帶調試資訊的Debug版本,VC6中“Project Setting->Link (Category:General)”預設勾選“Generate
debug info”,相應VC2005中的“項目屬性->配置屬性->連結器->調試->產生調試資訊”預設選項為“是(/DEBUG)”。

1.*.obj檔案和*.lib檔案

obj:Intermediate file,CPP對應的二進位代碼格式,是未經重定位的!

lib:Object File Library,若干個obj的集合,本質與obj相同!

使用時,obj和lib是沒有本質區別的,lib就是obj,使用lib地方都可以使用obj。

對於*.cpp檔案中的static變數或函數,在*.obj或*.lib中既有符號資訊又有實體定義。

對於*.cpp檔案中的extern變數或函數,在*.obj或*.lib中一般都會有符號資訊,實體既可以定義在本檔案中,也可以在其他檔案中定義。對於extern變數或函數,連結時,將在所有的*.obj或*.lib中尋找實體。

2.Lib和Exe協調

建立解決方案D:\ LibDemo\LibDemo(.dsw,.sln),在其下建立靜態庫(Win32 Static Library)項目MyLib(.dsp,.vcproj)和靜態庫測試專案(Win32
ConsoleApplication)MyLibDemo(.dsp,.vcproj)。首先需要為MyLibDemo項目附加標頭檔包含和連結庫包含。

(1)若設定MyLibDemo為啟動項目,執行F5調試命令,則在MyLib和MyLibDemo中的斷點處都會暫停。在MyLibDemo中可F11進入MyLib中的函數定義處。

(2)若設定MyLib為啟動項目,則要配置外部exe調用程式:

VC6中,“Project Setting->Debug(Category:General)”中的“Executable for debugsession”處填寫exe路徑,例如:D:\LibDemo\MyLibDemo\Debug\MyLibDemo.exe。相應VC2005中,“項目屬性->配置屬性->調試->命令”處填寫exe路徑。

執行F5調試命令,則在MyLib和MyLibDemo中的斷點處都會暫停。效果同(1)。

對於不同解決方案(.dsw,.sln)下的Lib項目和Exe項目協同調試方法同上。

3.Dll和Exe協調

dll項目往往會附帶產生一個對應的lib,是dll匯出函數和符號連結資訊。同lib項目產生的lib有點不同,這裡只有原型資訊,實體代碼在dll中。dll是可實際啟動並執行二進位代碼,其中有定位代碼。

建立解決方案D:\DllDemo\DllDemo(.dsw,.sln),在其下建立動態庫(Win32 Dynamic-Link Library)項目MyDll(.dsp,.vcproj)和動態庫測試專案(Win32
Console Application)MyDllDemo(.dsp,.vcproj)。

同Lib和Exe協調一樣,首先需要為Exe項目附加標頭檔(.h)包含和連結庫(.lib)包含。

(1)若設定MyDllDemo為啟動項目,為了使MyDll.dll對調試exe可見,設定MyDllDemo的調試工作目錄(Working
directory)為..\MyDll\Debug。

執行F5調試命令,則在MyDll和MyDllDemo中的斷點處都會暫停。在MyDllDemo中可F11進入MyDll中的函數定義處。

(2)若設定MyDll為啟動項目(例如def顯式動態連結程式庫的調試),則要配置外部exe調用程式:

VC6中,“Project Setting->Debug(Category:General)”中的“Executable for debugsession”處填寫exe路徑,例如:D:\DllDemo\MyDllDemo\Debug\MyDllDemo.exe。相應VC2005中,“項目屬性->配置屬性->調試->命令”處填寫exe路徑。

為了使MyDll.dll對調試exe可見,設定調試工作目錄(Working directory)為.\Debug。

執行F5調試命令,則在MyDll和MyDllDemo中的斷點處都會暫停。效果同(1)。

對於不同解決方案(.dsw,.sln)下的Dll項目和Exe項目協同調試方法同上。

4.產生後事件處理

在(1)和(2)中,除了指定調試工作目錄外,還可以處理產生後事件,將產生的連結庫檔案直接複製到應用程式Debug目錄下。具體的,在VC6中“Project
Setting ->Post-builtstep”或VC2005中“項目屬性->配置屬性->建置事件->產生後事件”輸入產生後處理命令:copy .\Debug\MyDll.dll..\MyDllDemo\Debug\MyDll.dll(有時需要使用xcopy以自動組建目錄)。當然,還可以將MyLib(MyDll)的輸出目錄直接指向MyLibDemo(MyDllDemo)的Debug下。

 

參考:

    《VisualC++ 6.0調試功能 圖解教程》

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.