VC 調試版(Debug Version)和發行版(Release Version)

調試是糾正或修改代碼,使之能夠順利地編譯、運行的過程。爲此,VC IDE提供了功能強大的調試和跟蹤工具。php

1.1.1 調試版(Debug Version)和發行版(Release Version

開發環境老是爲你的工程建立調試版和發行版。在調試版裏,咱們排查各類可能的程序錯誤,而後製做成發行版以得到較好的信息。這就是調試版與發行版的區別:前者包含了較多調試信息,最終執行文件較大,性能較差;後者最終執行文件較小,性能更好。具體地講,發行版和調試版區別有:express

1.       調試版下,可使用診斷和跟蹤宏,如ASSERTTRACEMFC類的DUMP功能也定義在調試版下。數組

2.       額外的變量初始化。編譯器會自動將你未初始化的變量逐每字節賦值爲0xCCsass

3.       內存分配監視。在調試版下,在堆上分配的內存都會記錄,作額外的初始化(0xCD),在釋放時,會將其內容逐字節置0xFD併發

怎樣配置調試版[C1] 或發行版?ide

調試版和發行版均可以從 Build | Configurations中增長,或者當這兩個配置已存在的狀況下,從Project | Settings命令下進行配置。二者在配置上主要有如下不一樣:函數

1. 兩個版本應該配置成不一樣的輸出文件夾。這在Project | Settings | General中的兩個編輯框中設定。工具

2. 調試版下,程序應該連接Debug版的c運行時庫、禁止代碼優化,並在C++屬性頁中的Preprocessor類別中加上預約義標識符_DEBUG。在Link屬性頁中的Debug類別中,選中DebugInfoMicrosoft Format選框。post

4.       發行版下,程序應該連接Release版的c運行時庫、設置代碼優化,不定義_DEBUG標識符,去掉DebugInfo選框中的選擇。性能

1.1.2 排除編譯錯誤

VC6.0的編譯器能夠報告大約1100個左右的錯誤,這還不包含警告。而在編譯和調試過程當中咱們還不只僅遇到編譯錯誤,也可能遇到連接錯誤和其餘錯誤,所以咱們只能講一些很常見、很重要的編譯錯誤。對咱們沒有列出來的編譯錯誤,解決它的最好辦法是,在output窗口中將光標定位在輸出行,而後按F1鍵以得到MSDN的幫助。若是MSDN的版本與你的VC不兼容,那麼你能夠用得到到Error xxxx做爲關鍵字在MSDN中搜索。目前這些錯誤的說明幫助出如今Visual C++ Programmer's Guide中的Build Errors條目下。

並不是錯誤

形如「Loaded 'C:\WINNT\system32\gdi32.dll', no matching symbolic information found.」這樣的報告不是錯誤。通常狀況下,咱們只須要跟蹤本身的源代碼,檢查在那裏發生了什麼錯誤。但有時候咱們也想看看,若是一個錯誤報告在系統DLL裏時到底是怎麼回事。Microsoft不肯意在系統DLL中包含調試信息,所以它提供調試符號幫助你跟蹤。隨VC6.0發行的有一個調試符號包,但其內容可能不能跟得上你操做系統版本。若是你須要適合你操做系統版本的調試符號,請到微軟更新網站上下載。

l       LNK2001錯誤

LNK2001錯誤報告一個不能識別的外部標識符。一般你使用一個函數或外部變量,都必須事先給出其聲明,不然就會產生這樣一個錯誤。能夠從如下幾個方面尋找緣由:

1.       使用內聯函數,但該內聯函數定義在.cpp文件中,而不是在.h文件中。

2.       聲明瞭函數或外部變量,但找不到它們的定義。

3.       程序入口設置錯誤,而且進一步提示_WinMain@16': Unresolved External Symbol或相似錯誤。在Windows程序中,程序並非最早從WinMain()Main()這樣的函數處開始執行,而是從WinMainCRTStartup()或MainCRTStratup函數處開始執行。這四個函數(其實是8個,每一個函數都有UNICODE版和單字節版)必須配套。若是進入點是WinMainCRTStartup (),則它期待在你的程序中找到一個WinMain()函數,若是找不到,則發生上述錯誤。

4.       在程序中使用了線程啓動函數_beginthread,但選擇的連接庫爲LIBC.LIB

其餘錯誤見MSDN

1.1.3 斷點和跟蹤

編譯錯誤都是靜態的,更多的錯誤發生在運行時。爲了排除運行時的錯誤,首先須要的是可以使正在運行的代碼停下來。VC6.0提供了多種斷點設置。

l       位置斷點

l       條件斷點:能夠設置如下條件爲真時中斷程序

1.       單變量值改變時

2.       單變量值判斷條件中斷,如K>0i == 5

3.       數組單元素或多元素值改變或值判斷條件中斷。

4.       指針:指針變量改變或指針所指內容改變

5.       監視固定內存值變化

6.       監視寄存器中值的變化,如 cs == 0等。

也能夠直接輸入斷點設置表達式,其語法是:

Advanced Syntax 詳解

{[function],[source],[exe] } location

{[function],[source],[exe] } variable_name

{[function],[source],[exe] } expression

 

括在{}對中的是上下文設置,這三項中任意一項均可省略,但省略前面的項時,應注意保留逗號。以下面的設置

是錯誤的:

{File.c, File.exe} .143 - Bad

正確的設置如

{Fun} .143 這樣在函數Fun的第143行設置了一個斷點。

 

更詳細的說明見下面的舉例:

{[function],[source],[exe] }  .100 - A line number (this may not work with some languages)

{[function],[source],[exe] }  @100 - A line number (this works for all languages)

{[function],[source],[exe] }  Traverse - A function name

{[function],[source],[exe] }  CMyWindow::OnCall - A function name

{[function],[source],[exe] }  00406030 - A memory address (decimal)

{[function],[source],[exe] }  0×1002A - A memory address (hexadecimal)

{function,[source],[exe] }     Label - A statement label. The context must include function since

Label is visible in the function’s scope.

 

更詳細的幫助,查看Visual C++ Programer’s GuidSetting Breakpoints When Values Change or Become True主題。

l       消息斷點

l       異常斷點

當程序發生異常時,咱們應該當即停下來,看看發生了什麼事情。默認地,當一個異常發生時,Debugger 將異常信息寫到Output 窗口中,並根據你的選擇決定是否當即中斷程序。這個設置在Debug菜單中的Exceptions選項中提供。這裏提供了兩個選項Stop AlwaysStop If Not Handled。當Stop If Not Handled被選中時,debugger僅僅往Output窗口中輸出一條信息,而並不停止程序,除非沒有這個異常最後也得不處處理。在有些狀況下,這會是一個有些晚的時機。當Stop Always被選中時,debugger會在異常處理代碼接管之前就中斷程序。

1.1.4 查看和修改程序運行狀態

開發環境提供了一系列的查看方式來臨視甚至修改程序的運行狀態。總共提供了六種查看窗口:

l       Watch窗口

Watch窗口用來查看和解碼中間變量,並容許你修改變量的值。Watch窗口共有四個Tab。每一個Tab都是一個ListView,由兩欄組成。左邊一欄爲變量名,右邊一欄則爲變量取值。只要在變量名欄輸入變量名並回車,就能夠獲得當前變量的值。下面是一些特殊的用法:

1.       列出數組中前n個元素的值:arrn

2.       查看UNICODE編碼的字符串值:strsu

3.       已知消息值,查對應的宏:messageValuewm

4.       查看窗口類標誌(Window class flag):flagValuewc

5.       查看當前線程最後錯誤報告:@errhr

6.       查看COM庫最後錯誤報告:@hres,hr

7.       查看當前寄存器值,把寄存器名看成變量名輸入就能夠了。

直接在右邊欄輸入新的取值,就會修改該變量的取值併發生做用。

l       Variables窗口

這個窗口始終跟蹤當前上下文中重要的變量取值。但不能增長對變量的跟蹤。它包含三個Tab

Auto窗口跟蹤當前聲明或前一個聲明中使用的變量,當你從一個函數調用中跳出時,還能夠顯示函數的返回值。

Locals窗口顯示對當前函數來講是局部的變量的取值。

This窗口顯示this指針所指對象取值。

此外,在Variables窗口的上部,還有一個Context的組合框,能夠用來切換當前查看的上下文。

l       CallStack窗口

這個窗口顯示了函數調用的狀況。當你的程序出現一個斷言時,你能夠用這個窗口把函數調用順序調出來,而且能夠知道調用時傳遞參數的狀況。雙擊窗口中列出的函數,能夠定位到源代碼中。

l       Memory窗口

Memory窗口的上部是一個地址輸入框。你能夠在這裏輸入0×00400000,由於這時進程的起始點,因此絕不奇怪,你會看到MZ這兩個字。Memory窗口支持定製顯示格式,並支持表達式。

Memory窗口的下面窗口處按右鍵,會出現一個菜單,容許你按單字節、雙字節十六進制或四字節十六進制來顯示內存的內容。

若是你願意麻煩一點,還有辦法獲得更準確的顯示。點Tools | Options,選擇Debug屬性頁,在這裏能夠決定以什麼形式顯示內存內容以及從什麼地址開始顯示。這裏提供了14種格式選項。此外,你還能夠輸入一個地址表達式。好比,若是要知道當前棧頂的狀況,在這裏輸入ESP

l       Disassembly窗口

這個窗口能夠用跟蹤優化代碼,或者是複雜表達式。

l       Registers窗口

Registers窗口顯示全部寄存器值,並容許你修改。它與Watch窗口的區別是,你不須要記住寄存器名,它老是把全部寄存器值給你列出來。

1.1.5 使用斷言和診斷[1]

VC提供了兩個斷言宏:ASSERTVERIFY。二者的區別是,在發行版中,ASSERT行不會執行,由於在發行版中,ASSERT宏被定義成

#define ASSERT /##/

這樣這行代碼被註釋掉,從而不會被編譯。VERIFY宏在發行版中被定義成

#define VERIFY

這樣VERIFY後面的代碼仍然加入編譯,從而獲得執行。

在你掌握了這兩個斷言的區別後,咱們將只講述ASSERT宏。ASSERT是一個帶參宏,其參數容許是一個表達式。當表達式的值爲假時,程序發生中斷並提示你是否進行調試。

除了使用條件判斷表達式外,ASSERT(0)也頗有用。它始終引發一個斷言錯,並提示你是否調試。你能夠把它放在一些你不指望程序運行到達的路徑上,若是事情一旦發生,則能夠直接進行調試。

VC還提供TRACE宏,以及它的姊妹宏TRACE0TRACE1TRACE2TRACE3TRACE宏的語法相似於printf,包括格式字符串的規定也是一致的。後面三個宏限定你使用一個格式字符串和一至三個變量。TRACE輸出到Output窗口,若是工具MFC TRACER中設置爲容許的話。

MFC還提供了對象診斷工具,即名爲Dump的函數。MFC庫中每一個從CObject繼承的類都有Dump的能力。若是你從MFC類庫中派生了某個類,在有必要的狀況下,最好重載這個函數。要記住,你重載的函數應該調用基類的Dump函數。另外,Dump函數只在調試版下可用。所以重載的函數也應該括在#ifdef _DEBUG宏中。

相關文章
相關標籤/搜索