青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++樂園

C/C++ 交流

  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
  12 隨筆 :: 18 文章 :: 14 評論 :: 0 Trackbacks
經(jīng)常在?CSDN?上看見有人問?Debug?運行正常但?Release?失敗的問題。以往的討論往往是經(jīng)驗性的,并沒有指出會這樣的真正原因是什么,要想找出真正的原因通常要憑運氣。最近我看了一些這方面的書,又參考了?CSDN?上的一些帖子,然后深入研究了一下關(guān)于二者的不同。以下是我的一些體會,拿來與大家共享。?--------------------------------------?本文主要包含如下內(nèi)容:
?1.?Debug?和?Release?編譯方式的本質(zhì)區(qū)別?
2.?哪些情況下?Release?版會出錯?
2.?怎樣"調(diào)試"?Release?版的程序?--------------------------------------?
關(guān)于Debug和Release之本質(zhì)區(qū)別的討論?一、Debug?和?Release?編譯方式的本質(zhì)區(qū)別?Debug?通常稱為調(diào)試版本,它包含調(diào)試信息,并且不作任何優(yōu)化,便于程序員調(diào)試程序。Release?稱為發(fā)布版本,它往往是進行了各種優(yōu)化,使得程序在代碼大小和運行速度上都是最優(yōu)的,以便用戶很好地使用。?Debug?和?Release?的真正秘密,在于一組編譯選項。下面列出了分別針對二者的選項(當(dāng)然除此之外還有其他一些,如/Fd?/Fo,但區(qū)別并不重要,通常他們也不會引起?Release?版錯誤,在此不討論)?Debug?版本:?/MDd?/MLd?或?/MTd?使用?Debug?runtime?library(調(diào)試版本的運行時刻函數(shù)庫)?/Od?關(guān)閉優(yōu)化開關(guān)?/D?"_DEBUG"?相當(dāng)于?#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?版本:?/MD?/ML?或?/MT?使用發(fā)布版本的運行時刻函數(shù)庫?/O1?或?/O2?優(yōu)化開關(guān),使程序最小或最快?/D?"NDEBUG"?關(guān)閉條件編譯調(diào)試代碼開關(guān)(即不編譯assert函數(shù))?/GF?合并重復(fù)的字符串,并將字符串常量放到只讀內(nèi)存,防止?被修改?實際上,Debug?和?Release?并沒有本質(zhì)的界限,他們只是一組編譯選項的集合,編譯器只是按照預(yù)定的選項行動。事實上,我們甚至可以修改這些選項,從而得到優(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)定,不會造成?Release?版錯誤;倒是由于?Debug?的?Runtime?Library?加強了對錯誤的檢測,如堆內(nèi)存分配,有時會出現(xiàn)?Debug?有錯但?Release?正常的現(xiàn)象。應(yīng)當(dāng)指出的是,如果?Debug?有錯,即使?Release?正常,程序肯定是有?Bug?的,只不過可能是?Release?版的某次運行沒有表現(xiàn)出來而已。?2.?優(yōu)化:這是造成錯誤的主要原因,因為關(guān)閉優(yōu)化時源程序基本上是直接翻譯的,而打開優(yōu)化后編譯器會作出一系列假設(shè)。這類錯誤主要有以下幾種:?(1)?幀指針(Frame?Pointer)省略(簡稱?FPO?):在函數(shù)調(diào)用過程中,所有調(diào)用信息(返回地址、參數(shù))以及自動變量都是放在棧中的。若函數(shù)的聲明與實現(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?消息響應(yīng)函數(shù)書寫錯誤。正確的應(yīng)為?afx_msg?LRESULT?OnMessageOwn(WPARAM?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,?LPARAM)?>?(&memberFxn)?},?(2)?volatile?型變量:volatile?告訴編譯器該變量可能被程序之外的未知方式修改(如系統(tǒng)、其他進程和線程)。優(yōu)化程序為了使程序性能提高,常把一些變量放在寄存器中(類似于?register?關(guān)鍵字),而其他進程只能對該變量所在的內(nèi)存進行修改,而寄存器中的值沒變。如果你的程序是多線程的,或者你發(fā)現(xiàn)某個變量的值與預(yù)期的不符而你確信已正確的設(shè)置了,則很可能遇到這樣的問題。這種錯誤有時會表現(xiàn)為程序在最快優(yōu)化出錯而最小優(yōu)化正常。把你認(rèn)為可疑的變量加上?volatile?試試。?(3)?變量優(yōu)化:優(yōu)化程序會根據(jù)變量的使用情況優(yōu)化變量。例如,函數(shù)中有一個未被使用的變量,在?Debug?版中它有可能掩蓋一個數(shù)組越界,而在?Release?版中,這個變量很可能被優(yōu)化調(diào),此時數(shù)組越界會破壞棧中有用的數(shù)據(jù)。當(dāng)然,實際的情況會比這復(fù)雜得多。與此有關(guān)的錯誤有:

?●?非法訪問,包括數(shù)組越界、指針錯誤等。
例如?void?fn(void)?{?int?i;?i?=?1;?int?a[4];?{?int?j;?j?=?1;?}?a[-1]?=?1;//當(dāng)然錯誤不會這么明顯,例如下標(biāo)是變量?a[4]?=?1;?}?j?雖然在數(shù)組越界時已出了作用域,但其空間并未收回,因而?i?和?j?就會掩蓋越界。而?Release?版由于?i、j?并未其很大作用可能會被優(yōu)化掉,從而使棧被破壞。?3.?_DEBUG?與?NDEBUG?:當(dāng)定義了?_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?斷言?ATLASSERT(?booleanExpression?);?此外,TRACE()?宏的編譯也受?_DEBUG?控制。?所有這些斷言都只在?Debug版中才被編譯,而在?Release?版中被忽略。唯一的例外是?VERIFY()?。事實上,這些宏都是調(diào)用了?assert()?函數(shù),只不過附加了一些與庫有關(guān)的調(diào)試代碼。如果你在這些宏中加入了任何程序代碼,而不只是布爾表達式(例如賦值、能改變變量值的函數(shù)調(diào)用?等),那么?Release?版都不會執(zhí)行這些操作,從而造成錯誤。初學(xué)者很容易犯這類錯誤,查找的方法也很簡單,因為這些宏都已在上面列出,只要利用?VC++?的?Find?in?Files?功能在工程所有文件中找到用這些宏的地方再一一檢查即可。另外,有些高手可能還會加入?#ifdef?_DEBUG?之類的條件編譯,也要注意一下。?順便值得一提的是?VERIFY()?宏,這個宏允許你將程序代碼放在布爾表達式里。這個宏通常用來檢查?Windows?API?的返回值。有些人可能為這個原因而濫用?VERIFY()?,事實上這是危險的,因為?VERIFY()?違反了斷言的思想,不能使程序代碼和調(diào)試代碼完全分離,最終可能會帶來很多麻煩。因此,專家們建議盡量少用這個宏。?4.?/GZ?選項:這個選項會做以下這些事?(1)?初始化內(nèi)存和變量。包括用?0xCC?初始化所有自動變量,0xCD?(?Cleared?Data?)?初始化堆中分配的內(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ù)值也很少遇到,而且這些值也很容易辨認(rèn),因此這很有利于在?Debug?版中發(fā)現(xiàn)?Release?版才會遇到的錯誤。要特別注意的是,很多人認(rèn)為編譯器會用?0?來初始化變量,這是錯誤的(而且這樣很不利于查找錯誤)。?(2)?通過函數(shù)指針調(diào)用函數(shù)時,會通過檢查棧指針驗證函數(shù)調(diào)用的匹配性。(防止原形不匹配)?(3)?函數(shù)返回前檢查棧指針,確認(rèn)未被修改。(防止越界訪問和原形不匹配,與第二項合在一起可大致模擬幀指針省略?FPO?)?通常?/GZ?選項會造成?Debug?版出錯而?Release?版正常的現(xiàn)象,因為?Release?版中未初始化的變量是隨機的,這有可能使指針指向一個有效地址而掩蓋了非法訪問。?除此之外,/Gm?/GF?等選項造成錯誤的情況比較少,而且他們的效果顯而易見,比較容易發(fā)現(xiàn)。?三、怎樣"調(diào)試"?Release?版的程序?遇到?Debug?成功但?Release?失敗,顯然是一件很沮喪的事,而且往往無從下手。如果你看了以上的分析,結(jié)合錯誤的具體表現(xiàn),很快找出了錯誤,固然很好。但如果一時找不出,以下給出了一些在這種情況下的策略。?1.?前面已經(jīng)提過,Debug?和?Release?只是一組編譯選項的差別,實際上并沒有什么定義能區(qū)分二者。我們可以修改?Release?版的編譯選項來縮小錯誤范圍。如上所述,可以把?Release?的選項逐個?注:那篇文章到此就完了,好像還有一些沒了。

在VC中當(dāng)整個工程較大時,軟件時常為出現(xiàn)在DEBUG狀態(tài)下能運行而在RELEASE狀態(tài)下無法運行的情況。由于開發(fā)者通常在DEBUG狀態(tài)下開發(fā)軟件,所以這種情況時常是在我們辛苦工作一兩個月后,滿懷信心的準(zhǔn)備將軟件發(fā)行時發(fā)生。為了避免無謂的損失,我們最好進行以下的檢查:?1、時常測試軟件的兩種版本。?2、不要輕易將問題歸結(jié)為DEBUG/RELEASE問題,除非你已經(jīng)充分對兩種版本進行了測試。?3、預(yù)處理的不同,也有可能引起這樣的問題。出現(xiàn)問題的一種可能性是在不同版本的編譯間定義了不同的預(yù)處理標(biāo)記。請對你的DEBUG版本的軟件試一下以下改動:?在"Project?Setting(ALT-F7)"?中的C/C++項中設(shè)置目錄(category)為"General",并且改動"_DEBUG"定義為"NDEBUG".?設(shè)置目錄為"Preprocessor"并且添加定義"_DEBUG到"Undefined?Symbols"輸入框.?選擇Rebuild?ALL,重新編譯.?如果經(jīng)過編譯的程序產(chǎn)生了問題,請對代碼進行如下改動:?將ASSERT()?改為?VERIFY().?找出定義在"#ifdef?_DEBUG"中的代碼,如果在RELEASE版本中需要這些代碼請將他們移到定義外。?查找TRACE(...)中代碼,因為這些代碼在RELEASE中也不被編譯。?所以請認(rèn)真檢查那些在RELEASE中需要的代碼是否并沒有被便宜。?4、變量的初始化所帶來的不同,在不同的系統(tǒng),或是在DEBUG/RELEASE版本間都存在這樣的差異,所以請對變量進行初始化。?5、是否在編譯時已經(jīng)有了警告?請將警告級別設(shè)置為3或4,然后保證在編譯時沒有警告出現(xiàn).?6、是否改動了資源文件.?7、此外對RELEASE版本的軟件也可以進行調(diào)試,請做如下改動:?在"Project?Settings"?中?"C++/C?"?項目下設(shè)置?"category"?為?"General"?并且將"Debug?Info"設(shè)置為?"Program?Database".?在"Link"項目下選中"Generate?Debug?Info"檢查框。?"Rebuild?All"?如此做法會產(chǎn)生的一些限制:?無法獲得在MFC?DLL中的變量的值。?必須對該軟件所使用的所有DLL工程都進行改動。?另:?MS?BUG:MS的一份技術(shù)文檔中表明,在VC5中對于DLL的"Maximize?Speed"優(yōu)化選項并未被完全支持,因此這將會引起內(nèi)存錯誤并導(dǎo)致程序崩潰。
posted on 2007-02-26 16:57 小不懂^_^ 閱讀(4050) 評論(1)  編輯 收藏 引用

評論

# re: Debug 運行正常但 Release 失敗的問題,Debug 和 Release 編譯方式的本質(zhì)區(qū)別 2015-04-08 16:41 88876
到處都是復(fù)制的內(nèi)容  回復(fù)  更多評論
  


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


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲欧美精品中文字幕在线| 亚洲欧洲视频在线| 亚洲国产欧美一区| 亚洲精品自在久久| 久久国产毛片| 久久精品视频va| 午夜精品剧场| 久久er99精品| 欧美国产视频一区二区| 这里只有精品视频在线| 日韩亚洲国产欧美| 在线一区二区三区四区| 99国产精品久久久| 午夜精品久久久久久久久久久久久| 亚洲欧美视频| 一本一本久久a久久精品综合麻豆| 亚洲欧洲日产国产综合网| 亚洲人体一区| 在线综合视频| 你懂的国产精品| 欧美成人首页| 亚洲线精品一区二区三区八戒| 亚洲裸体在线观看| 亚洲一区二区高清视频| 久久精品视频在线| 欧美激情中文字幕乱码免费| 欧美日本一道本| 国产精品香蕉在线观看| 激情文学一区| 久久av在线看| 99视频精品免费观看| 久久蜜桃资源一区二区老牛| 国产精品毛片a∨一区二区三区| 黄色小说综合网站| 午夜伦欧美伦电影理论片| 国产精品每日更新在线播放网址| 欧美国产欧美亚洲国产日韩mv天天看完整 | 狼狼综合久久久久综合网| 久久精品最新地址| 国产亚洲高清视频| 午夜性色一区二区三区免费视频| 亚洲精品1区2区| 欧美电影免费观看网站| 在线观看一区二区精品视频| 香蕉乱码成人久久天堂爱免费| 一区二区三区回区在观看免费视频| 老司机成人网| 亚洲另类自拍| 亚洲精品乱码久久久久久日本蜜臀| 狂野欧美激情性xxxx欧美| 亚洲电影有码| 日韩视频免费观看| 亚洲美女黄色片| 精品69视频一区二区三区| 欧美风情在线观看| 欧美日韩国产bt| 欧美专区日韩专区| 麻豆freexxxx性91精品| 一区二区三区毛片| 亚洲欧美一区二区三区久久| 韩国三级电影久久久久久| 欧美成人日韩| 国产精品自拍网站| 国产综合一区二区| 欧美高潮视频| 国产色视频一区| 亚洲欧洲久久| 一区二区在线看| 亚洲男人的天堂在线| 亚洲第一精品福利| 欧美一区二区三区视频免费| 亚洲深夜激情| 欧美国产91| 亚洲国产福利在线| 黑人中文字幕一区二区三区| 国产精品欧美久久久久无广告| 国产精品伊人日日| 亚洲最新合集| 亚洲一级黄色片| 欧美日韩国产在线观看| 亚洲福利小视频| 亚洲欧洲午夜| 欧美激情一区二区三级高清视频| 欧美成人黄色小视频| 亚洲成人在线网站| 你懂的视频一区二区| 亚洲激情国产精品| 狠狠色香婷婷久久亚洲精品| 亚洲自拍啪啪| 老司机成人在线视频| 在线日韩av| 欧美成人免费播放| 在线观看国产日韩| 久久综合色播五月| 亚洲精品视频一区二区三区| 亚洲视频在线免费观看| 国产欧美短视频| 另类激情亚洲| 99re热精品| 美女主播一区| 欧美亚洲一区二区在线| 久久国产精品久久久久久电车| 国产亚洲一区二区三区在线播放| 久久综合伊人77777蜜臀| 日韩一级免费| 亚洲国产小视频| 性欧美8khd高清极品| 亚洲国产欧美一区二区三区久久| 国产精品99一区| 欧美日韩成人精品| 老司机精品福利视频| 性感少妇一区| 亚洲欧美日韩国产一区| 亚洲精品影院| 一本久道久久综合狠狠爱| 欧美国产成人在线| 久热成人在线视频| 久久久久久一区| 欧美亚洲网站| 中文欧美在线视频| 亚洲日韩视频| 夜夜嗨av色一区二区不卡| 亚洲另类在线视频| 亚洲视频一区二区| 亚洲一级特黄| 欧美亚洲在线观看| 欧美一区二区在线免费播放| 欧美一区二区视频观看视频| 欧美一区免费视频| 亚洲欧美日韩天堂| 亚洲欧美日本另类| 久久精品人人做人人爽| 美女视频网站黄色亚洲| 亚洲黄页视频免费观看| 91久久精品www人人做人人爽 | 亚洲高清一区二| 亚洲裸体在线观看| 亚洲中午字幕| 在线 亚洲欧美在线综合一区| 一区免费视频| 久久成人免费视频| 亚洲精品社区| 免费日本视频一区| 国产亚洲一区二区三区在线播放| 亚洲乱码国产乱码精品精| 久久久久久久999| 亚洲一区中文| 国产精品红桃| 亚洲一区999| 亚洲国产欧美另类丝袜| 久久久www| 国产一级一区二区| 亚洲欧美日韩成人| 在线视频精品| 一本色道**综合亚洲精品蜜桃冫| 欧美性猛交99久久久久99按摩 | 国产日韩欧美日韩| 亚洲影音一区| 日韩午夜黄色| 国产精品日产欧美久久久久| 亚洲视频一区| 久久riav二区三区| 国语自产精品视频在线看| 欧美怡红院视频| 欧美在线亚洲综合一区| 在线成人av| 亚洲精品免费看| 国产精品女主播一区二区三区| 亚洲一二区在线| 欧美一区二区三区免费在线看| 韩国一区二区三区在线观看| 久久人人97超碰国产公开结果 | 欧美日韩高清不卡| 先锋资源久久| 亚洲精一区二区三区| 亚洲精品乱码久久久久久日本蜜臀 | 亚洲一区二区伦理| 亚洲欧美一区二区激情| 亚洲电影在线观看| 亚洲欧美www| 一区二区三区视频观看| 欧美专区福利在线| 亚洲一区二区三区中文字幕| 久久免费视频一区| 午夜精品福利一区二区蜜股av| 久久久久国产精品午夜一区| 亚洲精品国产拍免费91在线| 欧美在线视频一区二区三区| 午夜精品成人在线视频| 欧美日韩国产小视频在线观看| 女仆av观看一区| 国语自产精品视频在线看8查询8| 一区二区三区高清在线| 亚洲人成久久| 欧美激情乱人伦| 91久久亚洲| 亚洲影视九九影院在线观看| 欧美性生交xxxxx久久久| 亚洲另类自拍| 亚洲欧美999|