• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            road420

            導(dǎo)航

            <2009年11月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            統(tǒng)計(jì)

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            Debug 和 Release

            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  Build不對(duì)源代碼進(jìn)行調(diào)試,不考慮MFC的診斷宏,使用的是MFC  Release庫(kù),編譯十對(duì)應(yīng)用程序的速度進(jìn)行優(yōu)化,而Debug  Build則正好相反,它允許對(duì)源代碼進(jìn)行調(diào)試,可以定義和使用MFC的診斷宏,采用MFC  Debug庫(kù),對(duì)速度沒(méi)有優(yōu)化。    


            一、Debug  和  Release  編譯方式的本質(zhì)區(qū)別  

            Debug  通常稱為調(diào)試版本,它包含調(diào)試信息,并且不作任何優(yōu)化,便于程序員調(diào)試程序。Release  稱為發(fā)布版本,它往往是進(jìn)行了各種優(yōu)化,使得程序在代碼大小和運(yùn)行速度上都是最優(yōu)的,以便用戶很好地使用。  
            Debug  和  Release  的真正秘密,在于一組編譯選項(xiàng)。下面列出了分別針對(duì)二者的選項(xiàng)(當(dāng)然除此之外還有其他一些,如/Fd  /Fo,但區(qū)別并不重要,通常他們也不會(huì)引起  Release  版錯(cuò)誤,在此不討論)  

            Debug  版本:  
            /MDd  /MLd  或  /MTd  使用  Debug  runtime  library(調(diào)試版本的運(yùn)行時(shí)刻函數(shù)庫(kù))  
            /Od  關(guān)閉優(yōu)化開關(guān)  
            /D  &quot;_DEBUG&quot;  相當(dāng)于  #define  _DEBUG,打開編譯調(diào)試代碼開關(guān)(主要針對(duì)  
            assert函數(shù))  
            /ZI  創(chuàng)建  Edit  and  continue(編輯繼續(xù))數(shù)據(jù)庫(kù),這樣在調(diào)試過(guò)  
            程中如果修改了源代碼不需重新編譯  
            /GZ  可以幫助捕獲內(nèi)存錯(cuò)誤  
            /Gm  打開最小化重鏈接開關(guān),減少鏈接時(shí)間  

            Release  版本:    
            /MD  /ML  或  /MT  使用發(fā)布版本的運(yùn)行時(shí)刻函數(shù)庫(kù)  
            /O1  或  /O2  優(yōu)化開關(guān),使程序最小或最快  
            /D  &quot;NDEBUG&quot;  關(guān)閉條件編譯調(diào)試代碼開關(guān)(即不編譯assert函數(shù))  
            /GF  合并重復(fù)的字符串,并將字符串常量放到只讀內(nèi)存,防止  
            被修改  

            實(shí)際上,Debug  和  Release  并沒(méi)有本質(zhì)的界限,他們只是一組編譯選項(xiàng)的集合,編譯器只是按照預(yù)定的選項(xiàng)行動(dòng)。事實(shí)上,我們甚至可以修改這些選項(xiàng),從而得到優(yōu)化過(guò)的調(diào)試版本或是帶跟蹤語(yǔ)句的發(fā)布版本。  

            二、哪些情況下  Release  版會(huì)出錯(cuò)  

            有了上面的介紹,我們?cè)賮?lái)逐個(gè)對(duì)照這些選項(xiàng)看看  Release  版錯(cuò)誤是怎樣產(chǎn)生的  

            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í)源程序基本上是直接翻譯的,而打開優(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ù)書寫錯(cuò)誤。正確的應(yīng)為  
            afx_msg  LRESULT  OnMessageOwn(WPARAM  wparam,  LPARAM  lparam);  
            ON_MESSAGE  宏包含強(qiáng)制類型轉(zhuǎn)換。防止這種錯(cuò)誤的方法之一是重定義  ON_MESSAGE  宏,把下列代碼加到  stdafx.h  中(在#include  &quot;afxwin.h&quot;之后),函數(shù)原形錯(cuò)誤時(shí)編譯會(huì)報(bào)錯(cuò)  
            #undef  ON_MESSAGE  
            #define  ON_MESSAGE(message,  memberFxn)  \  
            {  message,  0,  0,  0,  AfxSig_lwl,  \  
            (AFX_PMSG)(AFX_PMSGW)(static_cast&lt;  LRESULT  (AFX_MSG_CALL  \  
            CWnd::*)(WPARAM,  LPARAM)  &gt;  (&memberFxn)  },  

            (2)  volatile  型變量:volatile  告訴編譯器該變量可能被程序之外的未知方式修改(如系統(tǒng)、其他進(jìn)程和線程)。優(yōu)化程序?yàn)榱耸钩绦蛐阅芴岣撸0岩恍┳兞糠旁诩拇嫫髦校愃朴? 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ò)誤等。例如  
            void  fn(void)  
            {  
            int  i;  
            i  =  1;  
            int  a[4];  
            {  
            int  j;  
            j  =  1;  
            }  
            a[-1]  =  1;//當(dāng)然錯(cuò)誤不會(huì)這么明顯,例如下標(biāo)是變量  
            a[4]  =  1;  
            }  
            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)? VERIFY()  違反了斷言的思想,不能使程序代碼和調(diào)試代碼完全分離,最終可能會(huì)帶來(lái)很多麻煩。因此,專家們建議盡量少用這個(gè)宏。  

            4.  /GZ  選項(xiàng):這個(gè)選項(xiàng)會(huì)做以下這些事  

            (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)? Release  版中未初始化的變量是隨機(jī)的,這有可能使指針指向一個(gè)有效地址而掩蓋了非法訪問(wèn)。  

            除此之外,/Gm  /GF  等選項(xiàng)造成錯(cuò)誤的情況比較少,而且他們的效果顯而易見,比較容易發(fā)現(xiàn)。  
            --------------------------------------------------------------  
            Release是發(fā)行版本,比Debug版本有一些優(yōu)化,文件比Debug文件小  
            Debug是調(diào)試版本,包括的程序信息更多  
            Release方法:  
            build-&gt;batch  build-&gt;build就OK.  

            -----------------------------------------------------  

            一、&quot;Debug是調(diào)試版本,包括的程序信息更多&quot;  

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

            二、一般發(fā)布release的方法除了hzh_shat(水)  所說(shuō)的之外,還可以project-&gt;Set  Active  Config,選中release版本。此后,按F5或F7編譯所得的結(jié)果就是release版本

            posted on 2009-11-21 22:39 深邃者 閱讀(294) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            武侠古典久久婷婷狼人伊人| 一本久久久久久久| 国产成人精品综合久久久久| 久久香蕉国产线看观看精品yw| 国产精品久久久久影院色| 99久久99久久精品免费看蜜桃| 久久免费国产精品一区二区| 国产午夜精品久久久久九九| 国产精品99久久久久久宅男小说| 久久精品一本到99热免费| 久久综合九色综合欧美就去吻| 乱亲女H秽乱长久久久| 久久国产成人精品国产成人亚洲| 久久久久久精品成人免费图片| 久久免费美女视频| 久久er99热精品一区二区| 要久久爱在线免费观看| 久久香蕉国产线看观看乱码| 亚洲国产精品无码久久一线| 久久性精品| 久久久精品日本一区二区三区 | 久久99国内精品自在现线| 久久精品亚洲乱码伦伦中文| 99re久久精品国产首页2020| 亚洲人成精品久久久久| 久久久久久精品免费免费自慰| 久久精品国产亚洲Aⅴ蜜臀色欲| 精品久久久久久久久中文字幕| 亚洲色婷婷综合久久| 成人午夜精品无码区久久| 久久亚洲精品国产亚洲老地址 | 色偷偷888欧美精品久久久| 久久99久久99精品免视看动漫| 亚洲国产成人精品女人久久久 | 国产精品成人久久久久久久| 久久水蜜桃亚洲av无码精品麻豆 | 久久久99精品成人片中文字幕| 国产精品一久久香蕉产线看| 欧洲成人午夜精品无码区久久| 少妇内射兰兰久久| 国产精品久久精品|