版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、Debug 和 Release 編譯方式的本質(zhì)區(qū)別Debug 通常稱為調(diào)試版本,它包含調(diào)試信息,并且不作任何優(yōu)化,便于程序員調(diào)試程序。Release 稱為發(fā)布版本,它往往是進行了各種優(yōu)化,使得程序在代碼大小和運行速度上都是最優(yōu)的,以便用戶很好地使用。Debug 和 Release 的真正秘密,在于一組編譯選項。下面列出了分別針對二者的選項(當然除此之外還有其他一些,如/Fd /Fo,但區(qū)別并不重要,通常他們也不會引起Release 版錯誤,在此不討論Debug 版本參數(shù)含義使用 Debug runtime library(調(diào)試版本的運行時刻函數(shù)庫/MDd /MLd 或/MTd/Od 關(guān)閉優(yōu)化開
2、關(guān)/D "_DEBUG" 相當于 #define _DEBUG,打開編譯調(diào)試代碼開關(guān)(主要針對assert函數(shù) /ZI 創(chuàng)建 Edit and continue(編輯繼續(xù)數(shù)據(jù)庫,這樣在調(diào)試過程中如果修改了源代碼不需重新編譯/GZ 可以幫助捕獲內(nèi)存錯誤/Gm 打開最小化重鏈接開關(guān),減少鏈接時間Release 版本參數(shù)含義/MD /ML 或 /MT 使用發(fā)布版本的運行時刻函數(shù)庫/O1 或 /O2 優(yōu)化開關(guān),使程序最小或最快/D "NDEBUG" 關(guān)閉條件編譯調(diào)試代碼開關(guān)(即不編譯assert函數(shù)/GF 合并重復的字符串,并將字符串常量放到只讀內(nèi)存,防止被修改
3、實際上,Debug 和 Release 并沒有本質(zhì)的界限,他們只是一組編譯選項的集合,編譯器只是按照預定的選項行動。事實上,我們甚至可以修改這些選項,從而得到優(yōu)化過的調(diào)試版本或是帶跟蹤語句的發(fā)布版本。哪些情況下 Release 版會出錯有了上面的介紹,我們再來逐個對照這些選項看看 Release 版錯誤是怎樣產(chǎn)生的1. Runtime Library:鏈接哪種運行時刻函數(shù)庫通常只對程序的性能產(chǎn)生影響。調(diào)試版本的 Runtime Library 包含了調(diào)試信息,并采用了一些保護機制以幫助發(fā)現(xiàn)錯誤,因此性能不如發(fā)布版本。編譯器提供的 Runtime Library 通常很穩(wěn)定,不會造成 Relea
4、se 版錯誤;倒是由于 Debug 的 Runtime Library 加強了對錯誤的檢測,如堆內(nèi)存分配,有時會出現(xiàn) Debug 有錯但 Release 正常的現(xiàn)象。應當指出的是,如果 Debug 有錯,即使Release 正常,程序肯定是有 Bug 的,只不過可能是 Release 版的某次運行沒有表現(xiàn)出來而已。2. 優(yōu)化:這是造成錯誤的主要原因,因為關(guān)閉優(yōu)化時源程序基本上是直接翻譯的,而打開優(yōu)化后編譯器會作出一系列假設。這類錯誤主要有以下幾種:1. 幀指針(Frame Pointer省略(簡稱 FPO :在函數(shù)調(diào)用過程中,所有調(diào)用信息(返回地址、參數(shù)以及自動變量都是放在棧中的。若函數(shù)的聲明
5、與實現(xiàn)不同(參數(shù)、返回值、調(diào)用方式,就會產(chǎn)生錯誤但 Debug 方式下,棧的訪問通過 EBP 寄存器保存的地址實現(xiàn),如果沒有發(fā)生數(shù)組越界之類的錯誤(或是越界“不多”,函數(shù)通常能正常執(zhí)行;Release 方式下,優(yōu)化會省略 EBP ?;分羔?這樣通過一個全局指針訪問棧就會造成返回地址錯誤是程序崩潰。C+ 的強類型特性能檢查出大多數(shù)這樣的錯誤,但如果用了強制類型轉(zhuǎn)換,就不行了。你可以在 Release 版本中強制加入 /Oy- 編譯選項來關(guān)掉幀指針省略,以確定是否此類錯誤。此類錯誤通常有:MFC 消息響應函數(shù)書寫錯誤。正確的應為:afx_msg LRESULT OnMessageOwn(WPAR
6、AM wparam, LPARAM lparam;ON_MESSAGE 宏包含強制類型轉(zhuǎn)換。防止這種錯誤的方法之一是重定義ON_MESSAGE 宏,把下列代碼加到 stdafx.h 中(在#include"afxwin.h"之后,函數(shù)原形錯誤時編譯會報錯。#undef ON_MESSAGE#define ON_MESSAGE(message, memberFxn message, 0, 0, 0, AfxSig_lwl, (AFX_PMSG(AFX_PMSGW(static_cast< LRESULT (AFX_MSG_CALL CWnd:*(WPARAM, LPAR
7、AM > (&memberFxn ,2. volatile 型變量:volatile 告訴編譯器該變量可能被程序之外的未知方式修改(如系統(tǒng)、其他進程和線程。優(yōu)化程序為了使程序性能提高,常把一些變量放在寄存器中(類似于 register 關(guān)鍵字,而其他進程只能對該變量所在的內(nèi)存進行修改,而寄存器中的值沒變。如果你的程序是多線程的,或者你發(fā)現(xiàn)某個變量的值與預期的不符而你確信已正確的設置了,則很可能遇到這樣的問題。這種錯誤有時會表現(xiàn)為程序在最快優(yōu)化出錯而最小優(yōu)化正常。把你認為可疑的變量加上 volatile 試試。3. 變量優(yōu)化:優(yōu)化程序會根據(jù)變量的使用情況優(yōu)化變量。例如,函數(shù)中有一個
8、未被使用的變量,在 Debug 版中它有可能掩蓋一個數(shù)組越界,而在Release 版中,這個變量很可能被優(yōu)化調(diào),此時數(shù)組越界會破壞棧中有用的數(shù)據(jù)。當然,實際的情況會比這復雜得多。與此有關(guān)的錯誤有:非法訪問,包括數(shù)組越界、指針錯誤等。例如void fn(voidint i;i = 1;int a4;int j;j = 1;a-1 = 1;/當然錯誤不會這么明顯,例如下標是變量a4 = 1;j 雖然在數(shù)組越界時已出了作用域,但其空間并未收回,因而 i 和 j就會掩蓋越界。而 Release 版由于 i、j 并未其很大作用可能會被優(yōu)化掉,從而使棧被破壞。3. _DEBUG 與 NDEBUG :當定義
9、了 _DEBUG 時,assert( 函數(shù)會被編譯,而 NDEBUG 時不被編譯。除此之外,VC+中還有一系列斷言宏。這包括:斷言類型定義ANSI C 斷言void assert(int expression ;C Runtime Lib 斷言_ASSERT( booleanExpression ;_ASSERTE( booleanExpression ;MFC 斷言ASSERT( booleanExpression ;VERIFY( booleanExpression ;ASSERT_VALID( pObject ;ASSERT_KINDOF( classname, pobject ;ATL
10、 斷言ATLASSERT( booleanExpression ;此外,TRACE( 宏的編譯也受 _DEBUG 控制。所有這些斷言都只在 Debug版中才被編譯,而在 Release 版中被忽略。唯一的例外是VERIFY( 。事實上,這些宏都是調(diào)用了 assert( 函數(shù),只不過附加了一些與庫有關(guān)的調(diào)試代碼。如果你在這些宏中加入了任何程序代碼,而不只是布爾表達式(例如賦值、能改變變量值的函數(shù)調(diào)用等,那么 Release 版都不會執(zhí)行這些操作,從而造成錯誤。初學者很容易犯這類錯誤,查找的方法也很簡單,因為這些宏都已在上面列出,只要利用VC+ 的 Find in Files 功能在工程所有文件中
11、找到用這些宏的地方再一一檢查即可。另外,有些高手可能還會加入 #ifdef _DEBUG 之類的條件編譯,也要注意一下。順便值得一提的是 VERIFY( 宏,這個宏允許你將程序代碼放在布爾表達式里。這個宏通常用來檢查 Windows API 的返回值。有些人可能為這個原因而濫用 VERIFY( ,事實上這是危險的,因為 VERIFY( 違反了斷言的思想,不能使程序代碼和調(diào)試代碼完全分離,最終可能會帶來很多麻煩。因此,專家們建議盡量少用這個宏。4. /GZ 選項:這個選項會做以下這些事:1. 初始化內(nèi)存和變量。包括用 0xCC 初始化所有自動變量,0xCD ( ClearedData 初始化堆中
12、分配的內(nèi)存(即動態(tài)分配的內(nèi)存,例如 new ,0xDD ( Dead Data 填充已被釋放的堆內(nèi)存(例如 delete ,0xFD( deFencde Data 初始化受保護的內(nèi)存(debug 版在動態(tài)分配內(nèi)存的前后加入保護內(nèi)存以防止越界訪問,其中括號中的詞是微軟建議的助記詞。這樣做的好處是這些值都很大,作為指針是不可能的(而且 32 位系統(tǒng)中指針很少是奇數(shù)值,在有些系統(tǒng)中奇數(shù)的指針會產(chǎn)生運行時錯誤,作為數(shù)值也很少遇到,而且這些值也很容易辨認,因此這很有利于在 Debug 版中發(fā)現(xiàn)Release 版才會遇到的錯誤。要特別注意的是,很多人認為編譯器會用 0 來初始化變量,這是錯誤的(而且這樣很
13、不利于查找錯誤。2. 通過函數(shù)指針調(diào)用函數(shù)時,會通過檢查棧指針驗證函數(shù)調(diào)用的匹配性。(防止原形不匹配3. 函數(shù)返回前檢查棧指針,確認未被修改。(防止越界訪問和原形不匹配,與第二項合在一起可大致模擬幀指針省略 FPO 通常 /GZ 選項會造成 Debug 版出錯而 Release 版正常的現(xiàn)象,因為 Release 版中未初始化的變量是隨機的,這有可能使指針指向一個有效地址而掩蓋了非法訪問。除此之外,/Gm /GF 等選項造成錯誤的情況比較少,而且他們的效果顯而易見,比較容易發(fā)現(xiàn)。怎樣“調(diào)試” Release 版的程序遇到 Debug 成功但 Release 失敗,顯然是一件很沮喪的事,而且往往
14、無從下手。如果你看了以上的分析,結(jié)合錯誤的具體表現(xiàn),很快找出了錯誤,固然很好。但如果一時找不出,以下給出了一些在這種情況下的策略。1. 前面已經(jīng)提過,Debug 和 Release 只是一組編譯選項的差別,實際上并沒有什么定義能區(qū)分二者。我們可以修改 Release 版的編譯選項來縮小錯誤范圍。如上所述,可以把Release 的選項逐個改為與之相對的 Debug 選項,如 /MD 改為 /MDd、/O1 改為 /Od,或運行時間優(yōu)化改為程序大小優(yōu)化。注意,一次只改一個選項,看改哪個選項時錯誤消失,再對應該選項相關(guān)的錯誤,針對性地查找。這些選項在 ProjectSettings. 中都可以直接通
15、過列表選取,通常不要手動修改。由于以上的分析已相當全面,這個方法是最有效的。2. 在編程過程中就要時常注意測試 Release 版本,以免最后代碼太多,時間又很緊。3. 在 Debug 版中使用 /W4 警告級別,這樣可以從編譯器獲得最大限度的錯誤信息,比如if( i =0 就會引起 /W4 警告。不要忽略這些警告,通常這是你程序中的 Bug 引起的。但有時 /W4 會帶來很多冗余信息,如未使用的函數(shù)參數(shù)警告,而很多消息處理函數(shù)都會忽略某些參數(shù)。我們可以用:#progma warning(disable: 4702 /禁止/.#progma warning(default: 4702 /重新允許來暫時禁止某個警告,或使用#progma warning(push, 3 /設置警告級別為 /W3/.#progma warning(pop /重設為 /W4來暫時改變警告級別,有時你可以只在認為可疑的那一部分代碼使用 /W4。4. 你也可以像 Debug 一樣調(diào)試你的 Release 版,只要加入調(diào)試符號。在Project/Settings. 中,選中 Settings for "Win32 Release
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 建筑工程公司宿舍租賃合同
- 林業(yè)開發(fā)電力設施安裝協(xié)議
- 醫(yī)療自建房施工合同模板
- 高級軟件開發(fā)工程師聘用合同
- 員工生育援助政策手冊
- 社會服務外網(wǎng)施工合同
- 城市綠化帶養(yǎng)護植樹合同
- 展覽館排水設施施工合同
- 商業(yè)活動策劃用車租賃合同樣本
- 珠寶行業(yè)合同專用章管理方案
- 軍隊文職(新聞專業(yè))招聘考試(重點)題庫200題(含答案解析)
- 人教版(2024)數(shù)學七年級上冊期末測試卷(含答案)
- 大部分分校:地域文化形考任務三-國開(CQ)-國開期末復習資料
- 2024年國家保密培訓
- 2024年全新初二生物上冊期末試卷及答案(人教版)
- DBJT 13-316-2019 聚合物透水混凝土路面技術(shù)規(guī)程
- 物業(yè)小區(qū)應急預案匯編
- JIS G4305-2021 冷軋不銹鋼板材、薄板材和帶材
- 園林生態(tài)學(冷生平)課后練習答案(完整版本)
- 部編版六年級上冊語文非連續(xù)性文本閱讀
- 智能水表項目可行性研究報告(范文模板)
評論
0/150
提交評論