免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Debug與Release版本的區(qū)別
Debug與Release版本的區(qū)別

    Debug 和 Release并沒(méi)有本質(zhì)的區(qū)別,他們只是VC預(yù)定義提供的兩組編譯選項(xiàng)的集合,編譯器只是按照預(yù)定的選項(xiàng)行動(dòng)。如果我們?cè)敢?,我們完全可以把Debug和Release的行為完全顛倒過(guò)來(lái)。當(dāng)然也可以提供其他的模式,例如自己定義一組編譯選項(xiàng),然后命名為MY_ABC等。習(xí)慣上,我們?nèi)匀桓敢馐褂肰C已經(jīng)定義好的名稱。
   Debug版本包括調(diào)試信息,所以要比Release版本大很多(可能大數(shù)百K至數(shù)M)。至于是否需要DLL支持,主要看你采用的編譯選項(xiàng)。如果是基于ATL的,則Debug和Release版本對(duì)DLL的要求差不多。如果采用的編譯選項(xiàng)為使用MFC動(dòng)態(tài)庫(kù),則需要MFC42D.DLL等庫(kù)支持,而Release版本需要MFC42.DLL支持。Release不對(duì)源代碼進(jìn)行調(diào)試,不考慮MFC的診斷宏,使用的是 MFC Release庫(kù),編譯時(shí)對(duì)應(yīng)用程序的速度進(jìn)行優(yōu)化,而Debug則正好相反,它允許對(duì)源代碼進(jìn)行調(diào)試,可以定義和使用MFC的 診斷宏,采用MFC Debug庫(kù),對(duì)速度沒(méi)有優(yōu)化。   
    既然Debug和 Release僅僅是編譯選項(xiàng)的不同,那么為什么要區(qū)分Debug和Release版本呢?
    Debug和Release,在我看來(lái)主要是針對(duì)其面向的目標(biāo)不同的而進(jìn)行區(qū)分的。Debug通常稱為調(diào)試版本,通過(guò)一系列編譯選項(xiàng)的配合,編譯的結(jié)果通常包含調(diào)試信息,而且不做任何優(yōu)化,以為開(kāi)發(fā)人員提供強(qiáng)大的應(yīng)用程序調(diào)試能力。而Release通常稱為發(fā)布版本,是為用戶使用的,一般客戶不允許在發(fā)布版本上進(jìn)行調(diào)試。所以不保存調(diào)試信息,同時(shí),它往往進(jìn)行了各種優(yōu)化,以期達(dá)到代碼最小和速度最優(yōu)。為用戶的使用提供便利。

    下面僅就默認(rèn)的Debug和Release版本的選項(xiàng)進(jìn)行 比較,詳細(xì)的編譯選項(xiàng)可以看MSDN的說(shuō)明。
我們將默認(rèn)的Debug和Release的選項(xiàng)設(shè)置進(jìn)行比較,過(guò)濾掉相同設(shè)置,主要的不同如下:
編譯選項(xiàng):/Od /D "_DEBUG" /Gm /RTC1 /MDd /Fo"Debug““" /ZI
鏈接選項(xiàng):/OUT:"D:“MyProject“logging“Debug“OptionTest.dll" /INCREMENTAL
Release設(shè)置:
編譯選項(xiàng):/O2 /GL /D "NDEBUG" /FD /MD /Fo"Release““" /Zi
鏈 接選項(xiàng):/OUT:"D:“MyProject“logging“Release“OptionTest.dll" /INCREMENTAL:NO

Debug  版本: 
/MDd  /MLd  或  /MTd  使用  Debug  runtime  library(調(diào)試版本的運(yùn)行 時(shí)刻函數(shù)庫(kù)) 
/Od  關(guān)閉優(yōu)化開(kāi)關(guān) 
/D  "_DEBUG"  相當(dāng)于  #define  _DEBUG,打開(kāi)編譯調(diào)試代碼 開(kāi)關(guān)(主要針對(duì)assert函數(shù)) 
/ZI  創(chuàng)建  Edit  and  continue數(shù)據(jù)庫(kù),在調(diào)試 過(guò)程中如果修改了源代碼不需重新編譯 
/GZ  可以幫助捕獲內(nèi)存錯(cuò)誤 
/Gm  打開(kāi)最小化重鏈接開(kāi)關(guān),減少鏈接時(shí) 間 
Release  版本:   
/MD  /ML  或  /MT  使用發(fā)布版本的運(yùn)行時(shí)刻函數(shù)庫(kù) 
/O1  或  /O2  優(yōu) 化開(kāi)關(guān),使程序最小或最快 
/D  "NDEBUG"  關(guān)閉條件編譯調(diào)試代碼開(kāi)關(guān)(即不編譯assert函數(shù)) 
/GF  合并重 復(fù)的字符串,并將字符串常量放到只讀內(nèi)存,防止被修改 

MDd與MD
    首先,Debug版本使用調(diào)試版本的運(yùn)行時(shí)庫(kù)(/MDd選項(xiàng)),Relase版本則使用的是發(fā)布版本的運(yùn)行時(shí)庫(kù)(vcrt.dll)。其區(qū)別主要在于運(yùn)行時(shí)的性能影響。調(diào)試版本的運(yùn)行時(shí)庫(kù)包含了調(diào)試信息,并采用了一些保護(hù)機(jī)制以幫助發(fā)現(xiàn)錯(cuò)誤,也因此,其性能不如發(fā)布版本。編譯器提供的RuntimeLibrary很穩(wěn)定,不會(huì)造成Release版本錯(cuò)誤,倒是由于Debug版本的RuntimeLibrary加強(qiáng)了對(duì)錯(cuò)誤的檢測(cè),如堆內(nèi)存分配檢查等,反而會(huì)報(bào)告錯(cuò)誤,應(yīng)當(dāng)指出,如果Debug有錯(cuò)誤,而Release版本正常,程序肯定是有Bug的,只是我們還沒(méi)有發(fā)現(xiàn)。
ZI與Zi
    其次,/ZI選項(xiàng)與/Zi選項(xiàng)。通過(guò)使用/ZI選項(xiàng),可以在調(diào)試過(guò)程修改代碼 而不需要重新編譯。這是個(gè)調(diào)試的好幫手,可如果我們使用Release版本,這將變得不可行。

Od與O2
/O2與/Od 選項(xiàng):Od是關(guān)閉編譯器優(yōu)化,普遍用于Debug版本。而O2選項(xiàng)是創(chuàng)建最快速代碼,這當(dāng)然是Release版本的不二選擇。

RTCx選 項(xiàng)
/RTCx選項(xiàng)讓編譯器插入動(dòng)態(tài)檢測(cè)代碼以幫助你檢測(cè)程序中的錯(cuò)誤。比如,它會(huì)將局部變量初始化為非零值。包括用0xCC初始化所有自動(dòng)變量,0xCD初始化堆中分配的內(nèi)存(即new的內(nèi)存),使用0xDD填充被釋放的內(nèi)存(即delete的內(nèi)存),0xFD初始化受保護(hù)的內(nèi)存(debug版在動(dòng)態(tài)分配內(nèi)存的前后加入保護(hù)內(nèi)存以防止越界訪問(wèn))。這樣做的好處是這些值都很大,一般不可能作為指針,考試,大提示作為數(shù)值也很少用到,而且這些值很容易辯認(rèn),因此有利于在Debug版本中發(fā)現(xiàn)Release版才會(huì)遇到的錯(cuò)誤。另外,通過(guò)函數(shù)指針調(diào)用函數(shù)時(shí),會(huì)通過(guò)檢查棧指針驗(yàn)證函數(shù)調(diào)用的匹配性(防止原型不匹配)。使用/RTCx選項(xiàng)會(huì)造成Debug版本出錯(cuò),而Release版本正常的現(xiàn)象,因?yàn)镽elease版中未初始化的變量是隨機(jī)的,很可能使指針指向了有效但是錯(cuò)誤的地址,從而掩蓋了錯(cuò)誤。這個(gè)編譯選項(xiàng)只能在/Od選項(xiàng)下使用。

Gm,INCREMENTAL or NO
編譯選項(xiàng)中的Gm和鏈接選項(xiàng)中的INCREMENTAL都只為一個(gè)目的,加快編譯速度。我們經(jīng)常遇上這樣的問(wèn)題,只修改了一個(gè)頭文件,結(jié)果卻造成所有動(dòng)態(tài)庫(kù)的重新編譯。而這兩個(gè)選項(xiàng)就是為了解決這樣的問(wèn)題。如果啟用了/Gm開(kāi)關(guān),編譯器在項(xiàng)目中的.idb文件中存儲(chǔ)了源文件和類定義之間的依賴關(guān)系。之后的編譯過(guò)程中使用.idb文件中的信息確定是否需要編譯某個(gè)源文件,哪怕是此源文件已經(jīng)包含了已修改的.h文件。
INCREMENTAL開(kāi)關(guān)默認(rèn)是開(kāi)啟的。使用增量鏈接生 成的可執(zhí)行文件或者動(dòng)態(tài)鏈接庫(kù)會(huì)大于非增量鏈接的程序,因?yàn)橛写a和數(shù)據(jù)的填充。另外,增量鏈接的文件還包含跳轉(zhuǎn)trunk以處理函數(shù)重定位到新地址。
MSDN 上明確指出:為確保最終發(fā)布版本不包含填充或者trunk,請(qǐng)非增量鏈接程序。

/GZ  選項(xiàng):做以下這些事 
1.初 始化內(nèi)存和變量。包括用  0xCC  初始化所有自動(dòng)變量,0xCD  (  Cleared  Data  ) 初始化堆中分配的內(nèi)存(即動(dòng)態(tài)分配 的內(nèi)存,例如  new  ),0xDD  (  Dead  Data  )  填充已被釋放的堆內(nèi)存(例 如 delete  ),0xFD(  deFencde  Data  )  初始化受保護(hù)的內(nèi)存(debug  版在動(dòng)態(tài)分配內(nèi)存的前后加入保護(hù)內(nèi)存以防止越界訪問(wèn)),其中括號(hào)中的詞是微軟建議的助記詞。這樣做的好處是這些值都很大,作為指針是不可能的(而且  32 位系統(tǒng)中指針很少是奇數(shù)值, 在有些系統(tǒng)中奇數(shù)的指針會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤),作為數(shù)值也很少遇到,而且這些值也很容易辨認(rèn),因此這很有利于在 Debug  版中發(fā) 現(xiàn)  Release  版才會(huì)遇到的錯(cuò)誤。要特別注意的是,很多人認(rèn)為編譯器會(huì)用  0 來(lái)初始化變量,這是錯(cuò)誤的(而且這樣很不利于查找錯(cuò) 誤)。 
2.   通過(guò)函數(shù)指針調(diào)用函數(shù)時(shí),會(huì)通過(guò)檢查棧指針驗(yàn)證函數(shù)調(diào)用的匹配性。(防止原形不匹配) 
3.   函數(shù)返回前檢查 棧指針,確認(rèn)未被修改。(防止越界訪問(wèn)和原形不匹配,與第二項(xiàng)合在一起可大致模擬幀指針省略  FPO  ) 

    通常  /GZ  選 項(xiàng)會(huì)造成  Debug  版出錯(cuò)而  Release  版正常的現(xiàn)象,因?yàn)?nbsp; Release  版中未初始化的變量是隨機(jī)的,這有可能使指針指向一 個(gè)有效地址而掩蓋了非法訪問(wèn)。 

_DEBUG與NDEBUG
這是最重要的一個(gè)選項(xiàng)。這兩個(gè)是編譯器的預(yù)處理器定義,默認(rèn)情況下_DEBUG用于Debug版本,而NDEBUG用于Release版本。 它們可以說(shuō)是重要的無(wú)以復(fù)加。因?yàn)?,assert系列的斷言僅僅在_DEBUG下生效!
下面是assert.h文件中摘出來(lái)的:
C++代碼
  1. #ifdef NDEBUG  
  2. #define assert(_Expression)     ((void)0)  
  3. #else  /* NDEBUG */  
  4. #ifdef __cplusplus  
  5. extern "C" {  
  6. #endif  /* __cplusplus */  
  7. _CRTIMP void __cdecl _wassert(__in_z const wchar_t * _Message, __in_z const wchar_t *_File, __in unsigned _Line);  
  8. #ifdef __cplusplus  
  9. }  
  10. #endif  /* __cplusplus */  
  11. #define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )  
  12. #endif  /* NDEBUG */  


可以看出在未定義_DEBUG時(shí),assert變成一條空語(yǔ)句不被執(zhí)行。
也就是說(shuō),我們現(xiàn)在所有發(fā)布的版本無(wú)法使 用斷言機(jī)制進(jìn)行程序調(diào)試。

相關(guān)經(jīng)驗(yàn):
1. 變量。
    大家都知道,debug跟release在初始化變量時(shí)所做的操作是不同的,debug是將每個(gè)字節(jié)位都賦成0xcc,而release的賦值近似于隨機(jī)。如果你的程序中的某個(gè)變量沒(méi)被初始化就被引用,就很有可能出現(xiàn)異常:用作控制變量將導(dǎo)致流程導(dǎo)向不一致;用作數(shù)組下標(biāo)將會(huì)使程序崩潰;更加可能是造成其他變量的不準(zhǔn)確而引起其他的錯(cuò)誤。所以在聲明變量后馬上對(duì)其初始化一個(gè)默認(rèn)的值是最簡(jiǎn)單有效的辦法,否則項(xiàng)目大了你找都沒(méi)地方找。代碼存在錯(cuò)誤在debug方式下可能會(huì)忽略而不被察覺(jué)到。debug方式下數(shù)組越界也大多不會(huì)出錯(cuò),在release中就暴露出來(lái)了,這個(gè)找起來(lái)就比較難了。
2. 自定義消息的消息參數(shù)。
   MFC為我們提供了很好的消息機(jī)制,更增加了自定義消息,好處我就不用多說(shuō)了。這也存在debug跟release的問(wèn)題嗎?答案是肯定的。在自定義消息的函數(shù)體聲明時(shí),時(shí)常會(huì)看到這樣的寫(xiě)法:afx_msg LRESULT OnMessageOwn();Debug情況下一般不會(huì)有任何問(wèn)題,而當(dāng)你在Release下且多線程或進(jìn)程間使用了消息傳遞時(shí)就會(huì)導(dǎo)致無(wú)效句柄之類的錯(cuò)誤。導(dǎo)致這個(gè)錯(cuò)誤直接原因是消息體的參數(shù)沒(méi)有添加,即應(yīng)該寫(xiě) 成:afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam);3. release模式下不出錯(cuò),但debug模式下報(bào)錯(cuò)。
    這種情況下大多也是因?yàn)榇a書(shū)寫(xiě)不正確引起的,查看MFC的源碼,可以發(fā)現(xiàn)好多ASSERT的語(yǔ)句(斷言),這個(gè)宏只是在debug模式下才有效,那么就清楚了,release版不報(bào)錯(cuò)是忽略了錯(cuò)誤而不是沒(méi)有錯(cuò)誤,這可能存在很大的隱患,因?yàn)槭荄ebug模式下,比較方便調(diào)試,好好的檢查自己的代碼,再此就不多說(shuō)了。
3. ASSERT, VERIFY, TRACE.......... 調(diào)試宏
    這種情況很容易解釋。舉個(gè)例子:請(qǐng)?jiān)赩C下輸入ASSERT然后選中按F12跳到宏定義的地方,這里你就能夠發(fā)現(xiàn)Debug中ASSERT要執(zhí)行AfxAssertFailedLine,而Release下的宏定義卻為\"#define ASSERT(f)((void)0)\"。所以注意在這些調(diào)試宏的語(yǔ)句不要用程序相關(guān)變量如i++寫(xiě)操作的語(yǔ)句。
VERIFY 是個(gè)例外,\"#define VERIFY(f) ((void)(f))\",即執(zhí)行。

哪些情況下Release版會(huì)出錯(cuò)? 
1.  Runtime  Library:鏈接哪種運(yùn)行時(shí)刻函數(shù)庫(kù)通常只對(duì)程序的性能產(chǎn)生影響。調(diào)試版本 的  Runtime Library  包含了調(diào)試信息,并采用了一些保護(hù)機(jī)制以幫助發(fā)現(xiàn)錯(cuò)誤,因此性能不如發(fā)布版本。編譯器提供 的  Runtime Library  通常很穩(wěn)定,不會(huì)造成  Release  版錯(cuò)誤;倒是由 于  Debug  的  Runtime  Library 加強(qiáng)了對(duì)錯(cuò)誤的檢測(cè),如堆內(nèi)存分配,有時(shí)會(huì)出現(xiàn)  Debug  有錯(cuò) 但  Release  正常的現(xiàn)象。應(yīng)當(dāng)指出的是,如果  Debug 有錯(cuò),即使  Release  正常,程序肯定是有  Bug  的,只不 過(guò)可能是  Release  版的某次運(yùn)行沒(méi)有表現(xiàn)出來(lái)而已。
 
2.  優(yōu)化:這是造成錯(cuò)誤的主要原因,因?yàn)殛P(guān)閉優(yōu)化時(shí)源程序基本上是直接翻譯的,而打開(kāi)優(yōu)化后編譯器會(huì)作出一系列假設(shè)。這類錯(cuò)誤主要有以下幾種: 
(1)  幀指針 (Frame  Pointer)省略(簡(jiǎn)稱  FPO ):在函數(shù)調(diào)用過(guò)程中,所有調(diào)用信息(返回地址、參數(shù))以及自動(dòng)變量都是放在棧中的。若函數(shù)的聲明與實(shí)現(xiàn)不同(參數(shù)、返回值、調(diào)用方式),就會(huì)產(chǎn)生錯(cuò)誤,但  Debug  方式下,棧的訪問(wèn)通過(guò)  EBP  寄存器保存的地址實(shí)現(xiàn),如果沒(méi)有發(fā)生數(shù)組越界之類的錯(cuò)誤(或是越界“不多”),函數(shù)通常能正常執(zhí)行;Release  方式下,優(yōu)化會(huì)省略  EBP ?;分羔?,這樣通過(guò)一個(gè)全局 指針訪問(wèn)棧就會(huì)造成返回地址錯(cuò)誤是程序崩潰。C++ 的強(qiáng)類型特性能檢查出大多數(shù)這樣的錯(cuò)誤,但如果用了強(qiáng)制類型轉(zhuǎn)換,就不行了。你可以 在  Release  版本中強(qiáng)制加入  /Oy- 編譯選項(xiàng)來(lái)關(guān)掉幀指針省略,以確定是否此類錯(cuò)誤。此類錯(cuò)誤通常有: 

MFC消息響應(yīng)函數(shù)書(shū)寫(xiě)錯(cuò)誤。正確的應(yīng)為 
afx_msg  LRESULT  OnMessageOwn(WPARAM  wparam,  LPARAM  lparam); 
ON_MESSAGE  宏 包含強(qiáng)制類型轉(zhuǎn)換。防止這種錯(cuò)誤的方法之一是重定義  ON_MESSAGE  宏,把下列代碼加到  stdafx.h  中 (在#include  "afxwin.h"之后),函數(shù)原形錯(cuò)誤時(shí)編譯會(huì)報(bào)錯(cuò) 
C++代碼
  1. #undef  ON_MESSAGE    
  2. #define  ON_MESSAGE(message,  memberFxn)  \    
  3. {  message,  0,  0,  0,  AfxSig_lwl,  \    
  4. (AFX_PMSG)(AFX_PMSGW)(static_cast<  LRESULT  (AFX_MSG_CALL  \    
  5. CWnd::*)(WPARAM,  LPARAM)  >  (&memberFxn)  },    


(2)  volatile  型變量:volatile 告訴編譯器該變量可能被程序之外的未知方式修改(如系統(tǒng)、其他進(jìn)程和線程)。優(yōu)化程序?yàn)榱耸钩绦蛐阅芴岣?,常把一些變量放在寄存器中(類似?nbsp;register  關(guān)鍵字),而其他進(jìn)程只能對(duì)該變量所在的內(nèi)存進(jìn)行修改,而寄存器中的值沒(méi)變。如果你的程序是多線程的,或者你發(fā)現(xiàn)某個(gè)變量的值與預(yù)期的不符而你確信已正確的設(shè)置了,則很可能遇到這樣的問(wèn)題。這種錯(cuò)誤有時(shí)會(huì)表現(xiàn)為程序在最快優(yōu)化出錯(cuò)而最小優(yōu)化正常。把你認(rèn)為可疑的變量加上  volatile  試試。 

(3)  變量?jī)?yōu)化:優(yōu)化程序會(huì)根據(jù)變量的使用情況優(yōu)化變量。例如,函數(shù)中有一個(gè)未被使用的變量,在  Debug 版中它有可能掩蓋一個(gè)數(shù)組越界,而在  Release  版中,這個(gè)變量很可能被優(yōu)化調(diào),此時(shí)數(shù)組越界會(huì)破壞棧中有用的數(shù)據(jù)。當(dāng)然,實(shí)際的情況會(huì)比這復(fù)雜得多。與此有關(guān)的錯(cuò)誤有: 
    非法訪問(wèn),包括數(shù)組越界、指針錯(cuò)誤 等。例如 
C++代碼
  1. void  fn(void)    
  2. {    
  3.     int  i;    
  4.     i  =  1;    
  5.    int  a[4];    
  6.    {    
  7.       int  j;    
  8.       j  =  1;    
  9.    }    
  10.    a[-1]  =  1; //當(dāng)然錯(cuò)誤不會(huì)這么明顯,例如下標(biāo)是變量    
  11.    a[4]  =  1;    
  12. }    

j  雖然在數(shù)組越界時(shí)已出了作用域,但其空間并未收回,因而  i  和  j  就會(huì)掩蓋越界。而  Release  版由于  i、j  并未其很大作用可能會(huì)被優(yōu)化掉,從而使棧被破壞。 

3.  _DEBUG  與  NDEBUG  :當(dāng)定義了  _DEBUG  時(shí),assert()  函數(shù)會(huì)被編譯, 而  NDEBUG  時(shí)不被編譯。除此之外,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  斷 言  ATLASSERT(  booleanExpression  ); 
此外,TRACE()  宏的編譯也受  _DEBUG  控 制。 

所有這些斷言都只在  Debug版中才被編譯,而在  Release  版中被忽略。唯一的例外 是  VERIFY() 。事實(shí)上,這些宏都是調(diào)用了  assert()  函數(shù),只不過(guò)附加了一些與庫(kù)有關(guān)的調(diào)試代碼。如果你在這些宏中加入了任何程序代碼,而不只是布爾表達(dá)式(例如賦值、能改變變量值的函數(shù)調(diào)用  等),那么  Release 版都不會(huì)執(zhí)行這些操作,從而造成錯(cuò)誤。初學(xué)者很容 易犯這類錯(cuò)誤,查找的方法也很簡(jiǎn)單,因?yàn)檫@些宏都已在上面列出,只要利用  VC++  的 Find  in  Files  功能在工程所有文件中 找到用這些宏的地方再一一檢查即可。另外,有些高手可能還會(huì)加入  #ifdef _DEBUG  之類的條件編譯,也要注意一下。 
順便值 得一提的是  VERIFY()  宏,這個(gè)宏允許你將程序代碼放在布爾表達(dá)式里。這個(gè)宏通常用來(lái)檢查  Windows API  的返回值。有些人 可能為這個(gè)原因而濫用  VERIFY()  ,事實(shí)上這是危險(xiǎn)的,因?yàn)?nbsp; VERIFY() 違反了斷言的思想,不能使程序代碼和調(diào)試代碼完全分離, 最終可能會(huì)帶來(lái)很多麻煩。因此,專家們建議盡量少用這個(gè)宏。 

一、"Debug是調(diào)試版本,包括的程序信息更多" 
補(bǔ)充:只有DEBUG版的程序才能設(shè)置斷點(diǎn)、單步執(zhí)行、使用 TRACE/ASSERT等調(diào)試輸出語(yǔ)句。REALEASE不包含任何調(diào)試信息,所以體積小、運(yùn)行速度快。

I.    內(nèi)存分配問(wèn)題  
   1.    變量未初始化。下面的程序在debug中運(yùn)行的很好。  
C++代碼
  1. thing    *    search(thing    *    something)     
  2. BOOL    found;     
  3. for(int    i    =    0;    i    <    whatever.GetSize();    i++)     
  4. {     
  5. if(whatever[i]->field    ==    something->field)     
  6. {    /*    found    it    */     
  7. found    =    TRUE;     
  8. break;     
  9. }    /*    found    it    */     
  10. }     
  11. if(found)     
  12. return    whatever[i];     
  13. else     
  14. return    NULL;     

   而在release中卻不行,因?yàn)閐ebug中會(huì)自動(dòng)給變量初始化found=FALSE,而在release版中則不會(huì)。所以盡可能的給變量、類或結(jié)構(gòu) 初始化。  
   
   2.    數(shù)據(jù)溢出的問(wèn)題  
   如:
C++代碼
  1. char    buffer[10];     
  2. int    counter;     
  3. lstrcpy(buffer,    "abcdefghik");     

   在debug版中buffer的NULL覆蓋了counter的高位,但是除非counter>16M,什么問(wèn)題也沒(méi)有。但是在release版中,counter可能被放在寄存器中,這樣NULL就覆蓋了buffer下面的空間,可能就是函數(shù)的返回地址,這將導(dǎo)致 ACCESS   ERROR。  
   
   3.    DEBUG版和RELEASE版的內(nèi)存分配方式是不同的    。如果你在DEBUG版中申請(qǐng)    ele   為    6*sizeof(DWORD)=24bytes,實(shí)際上分配給你的是32bytes(debug版以32bytes為單位分配),   而在release版,分配給你的就是24bytes(release版以8bytes為單位),所以在debug版中如果你寫(xiě)ele[6],可能不會(huì)有什么問(wèn)題,而在release版中,就有ACCESS    VIOLATE。  
   
   II.    ASSERT和VERIFY  
   
   1.    ASSERT在Release版本中是不會(huì)被編譯的。  
   
   ASSERT宏是這樣定義的  
C++代碼
  1.    
  2. #ifdef    _DEBUG     
  3. #define    ASSERT(x)    if(    (x)    ==    0)    report_assert_failure()     
  4. #else     
  5. #define    ASSERT(x)     
  6. #endif     

   實(shí)際上復(fù)雜一些,但無(wú)關(guān)緊要。假如你在這些語(yǔ)句中加了程序中必須要有的代碼  
   比如  
C++代碼
  1.    
  2. ASSERT(pNewObj    =    new    CMyClass);     
  3.    
  4. pNewObj->MyFunction();     
  
   這種時(shí)候Release版本中的pNewObj不會(huì)分配到空間  
   
   所以執(zhí)行到下一個(gè)語(yǔ)句的時(shí)候程序會(huì)報(bào)該程序執(zhí)行了非法操作的錯(cuò)誤。這時(shí)可以用VERIFY    :  
C++代碼
  1.    
  2. #ifdef    _DEBUG     
  3. #define    VERIFY(x)    if(    (x)    ==    0)    report_assert_failure()     
  4. #else     
  5. #define    VERIFY(x)    (x)     
  6. #endif   
 
   這樣的話,代碼在release版中就可以執(zhí)行了。  
   
   III.    參數(shù)問(wèn)題:  
   
   自定義消息的處理函數(shù),必須定義如下:  
   afx_msg    LRESULT    OnMyMessage(WPARAM,    LPARAM);  
   返回值必須是HRESULT型,否則Debug會(huì)過(guò),而Release出錯(cuò)  
   
   IV.    內(nèi)存分配  
   保證數(shù)據(jù)創(chuàng)建和清除的統(tǒng)一性:如果一個(gè)DLL提供一個(gè)能夠創(chuàng)建數(shù)據(jù)的函數(shù),那么這個(gè)DLL同時(shí)應(yīng)該提供一個(gè)函數(shù)銷毀這些數(shù)據(jù)。數(shù)據(jù)的創(chuàng)建和清除應(yīng)該在同一 個(gè)層次上。  
   
   V.    DLL的災(zāi)難  
   人們將不同版本DLL混合造成的不一致性形象的稱為    “動(dòng)態(tài)連接庫(kù)的地獄“(DLL    Hell)    ,甚至微軟自己也這么說(shuō) http://msdn.microsoft.com/library/techart/dlldanger1.htm)。  
   
   如果你的程序使用你自己的DLL時(shí)請(qǐng)注意:  
   
   1.    不能將debug和release版的DLL混合在一起使用。debug都是debug版,release版都是release版。  
   解決辦法是將debug和release的程序分別放在主程序的debug和release目錄下  
   
   2.    千萬(wàn)不要以為靜態(tài)連接庫(kù)會(huì)解決問(wèn)題,那只會(huì)使情況更糟糕。  
   
   VI.    RELEASE版中的調(diào)試    :  
   1.    將ASSERT()    改為    VERIFY()    。找出定義在"#ifdef   _DEBUG"中的代碼,如果在RELEASE版本中需要這些代碼請(qǐng)將他們移到定義外。查找TRACE(...)中代碼,因?yàn)檫@些代碼在RELEASE中也不被編譯。    請(qǐng)認(rèn)真檢查那些在RELEASE中需要的代碼是否并沒(méi)有被便宜。  
   2.    變量的初始化所帶來(lái)的不同,在不同的系統(tǒng),或是在DEBUG/RELEASE版本間都存在這樣的差異,所以請(qǐng)對(duì)變量進(jìn)行初始化。  
   3.    是否在編譯時(shí)已經(jīng)有了警告?請(qǐng)將警告級(jí)別設(shè)置為3或4,然后保證在編譯時(shí)沒(méi)有警告出現(xiàn).  

   VII.    將Project    Settings"    中    "C++/C    "   項(xiàng)目下優(yōu)化選項(xiàng)改為Disbale(Debug)。編譯器的優(yōu)化可能導(dǎo)致許多意想不到的錯(cuò)誤,請(qǐng)參http://www.pgh.net/~newcomer/debug_release.htm  
   
   1.    此外對(duì)RELEASE版本的軟件也可以進(jìn)行調(diào)試,請(qǐng)做如下改動(dòng):  
   
   在"Project Settings"中"C++/C"項(xiàng)目下設(shè)置"category"為"General"并且將"Debug    Info"設(shè)置為"Program Database"。  
   
   在"Link"項(xiàng)目下選中"Generate Debug Info"檢查框。  
   
   "Rebuild All"  
   
   如此做法會(huì)產(chǎn)生的一些限制:  
   
   無(wú)法獲得在MFC DLL中的變量的值。  
   
   必須對(duì)該軟件所使用的所有DLL工程都進(jìn)行改動(dòng)。  
   
   另:  
   
   1. MS BUG:MS的一份技術(shù)文檔中表明,在VC5中對(duì)于DLL的"Maximize    Speed"優(yōu)化選項(xiàng) 并未被完全支持,因此這將會(huì)引起內(nèi)存錯(cuò)誤并導(dǎo)致程序崩潰。  
   
   2. http://www.sysinternals.com/有一個(gè)程序DebugView,用來(lái)捕捉OutputDebugString的輸出,運(yùn)行起來(lái)后(估計(jì)是自設(shè)為systemdebugger)就可以觀看所有程序的OutputDebugString的輸出。此后,你可以脫離VC來(lái)運(yùn)行你的程序并觀看調(diào)試信息。  
   
   3.    有一個(gè)叫Gimpel    Lint的靜態(tài)代碼檢查工具,據(jù)說(shuō)比較好用http://www.gimpel.com/    不過(guò)要化$的。

Debug與Release不同的問(wèn)題在剛開(kāi)始編寫(xiě)代碼時(shí)會(huì)經(jīng)常發(fā)生,99%是因?yàn)槟愕拇a書(shū)寫(xiě)錯(cuò)誤而導(dǎo)致的,所以不要?jiǎng)硬粍?dòng)就說(shuō)系統(tǒng)問(wèn)題或編譯器問(wèn)題,努力找找自己的原因才是根本。我從前就常常遇到這情況,經(jīng)歷過(guò)一次次的教訓(xùn)后我就開(kāi)始注意了,現(xiàn)在我所寫(xiě)過(guò)的代碼我已經(jīng)好久沒(méi)遇到這種問(wèn)題了。下面是幾個(gè)避免的方面,即使沒(méi)有這種問(wèn)題也應(yīng)注意一下:
1. 注意變量的初始化,尤其是指針變量,數(shù)組變量的初始化(很大的情況下另作考 慮了)。
2. 自定義消息及其他聲明的標(biāo)準(zhǔn)寫(xiě)法
3. 使用調(diào)試宏時(shí)使用后最好注釋掉
4. 盡量使用 try - catch(...)
5. 盡量使用模塊,不但表達(dá)清楚而且方便調(diào)試。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
ios應(yīng)用:release與debug編譯方式的區(qū)別
Debug和Release編譯方式的本質(zhì)區(qū)別
vc下debug 版本和release版本的區(qū)別
VC程序在debug下運(yùn)行的是正常顯示的,在release下就不會(huì)顯示了,怎么回事???
VC++程序調(diào)試 - VC++ - 開(kāi)發(fā)語(yǔ)言 - 程序員之家
(4)C 調(diào)試技巧
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服