vc下關於debug和release的區別的討論(網上總結)
2008-09-17 02:30 p.m.
最近寫**過程中,發現 debug 下執行正常,release 下就會出現問題,百思不得其解,而release 下又無法進行除錯,於是只能採用printf方式逐步定位到問題所在處,才發現原來是給定的乙個陣列未初始化,導致後面處理異常。網上查詢了些資料,在這羅列彙總下,做為備忘~
一、debug 和 release 的區別
debug 通常稱為除錯版本,它包含除錯資訊,並且不作任何優化,便於程式設計師除錯程式。release 稱為發布版本,它往往是進行了各種優化,使得程式在**大小和執行速度上都是最優的,以便使用者很好地使用。
debug 和 release 的真正區別,在於一組編譯選項。
debug 版本
引數 含義
/mdd /mld 或 /mtd 使用 debug runtime library(除錯版本的執行時刻函式庫)
/od 關閉優化開關
/d "_debug" 相當於 #define _debug,開啟編譯除錯**開關(主要針對assert函式)
/zi
建立 edit and continue(編輯繼續)資料庫,這樣在除錯過程中如果修改了源**不需重新編譯
gz 可以幫助捕獲記憶體錯誤
release 版本
引數 含義
/md /ml 或 /mt 使用發布版本的執行時刻函式庫
/o1 或 /o2 優化開關,使程式最小或最快
/d "ndebug" 關閉條件編譯除錯**開關(即不編譯assert函式)
/gf 合併重複的字串,並將字串常量放到唯讀記憶體,防止被修改
debug 和 release 並沒有本質的界限,他們只是一組編譯選項的集合,編譯器只是按照預定的選項行動。
二、相關經驗:**http://dev.csdn.net/article/17/17068.shtm
1. 變數。
大家都知道,debug跟release在初始化變數時所做的操作是不同的,debug是將每個位元組位都賦成0xcc(注1),而release的賦值近似於隨機(我想是直接從記憶體中分配的,沒有初始化過)。這樣就明確了,如果你的程式中的某個變數沒被初始化就被引用,就很有可能出現異常:用作控制變數將導致流程導向不一致;用作陣列下標將會使程式崩潰;更加可能是造成其他變數的不準確而引起其他的錯誤。所以在宣告變數後馬上對其初始化乙個預設的值是最簡單有效的辦法,否則專案大了你找都沒地方找。**存在錯誤在debug方式下可能會忽略而不被察覺到,如debug方式下陣列越界也大多不會出錯,在release中就暴露出來了,這個找起來就比較難了:( 還是自己多加注意吧
2. 自定義訊息的訊息引數。
mfc為我們提供了很好的訊息機制,更增加了自定義訊息,好處我就不用多說了。這也存在debug跟release的問題嗎?答案是肯定的。在自定義訊息的函式體宣告時,時常會看到這樣的寫法:afx_msg lresult onmessageown(); debug情況下一般不會有任何問題,而當你在release下且多執行緒或程序間使用了訊息傳遞時就會導致無效控制代碼之類的錯誤。導致這個錯誤直接原因是訊息體的引數沒有新增,即應該寫成:afx_msg lresult onmessageown(wparam wparam, lparam lparam); (注2)
3. release模式下不出錯,但debug模式下報錯。
這種情況下大多也是因為**書寫不正確引起的,檢視mfc的原始碼,可以發現好多assert的語句(斷言),這個巨集只是在debug模式下才有效,那麼就清楚了,release版不報錯是忽略了錯誤而不是沒有錯誤,這可能存在很大的隱患,因為是debug模式下,比較方便除錯,好好的檢查自己的**,再此就不多說了。
4. assert, verify, trace..........除錯巨集
這種情況很容易解釋。舉個例子:請在vc下輸入assert然後選中按f12跳到巨集定義的地方,這裡你就能夠發現debug中assert要執行afxassertfailedline,而release下的巨集定義卻為"#define assert(f) ((void)0)"。所以注意在這些除錯巨集的語句不要用程式相關變數如i++寫操作的語句。verify是個例外,"#define verify(f) ((void)(f))",即執行,這裡的作用就不多追究了,有興趣可自己研究:)。
總結:
debug與release不同的問題在剛開始編寫**時會經常發生,99%是因為你的**書寫錯誤而導致的,所以不要動不動就說系統問題或編譯器問題,努力找找自己的原因才是根本。我從前就常常遇到這情況,經歷過一次次的教訓後我就開始注意了,現在我所寫過的**我已經好久沒遇到這種問題了。下面是幾個避免的方面,即使沒有這種問題也應注意一下:
1. 注意變數的初始化,尤其是指標變數,陣列變數的初始化(很大的情況下另作考慮了)。
2. 自定義訊息及其他宣告的標準寫法
3. 使用除錯巨集時使用後最好注釋掉
4. 盡量使用try - catch(...)
5. 盡量使用模組,不但表達清楚而且方便除錯。
注1:afc(afc) 網友提供:
debug版初始化成0xcc是因為0xcc在x86下是一條int 3單步中斷指令,這樣程式如果跑飛了遇到0xcc就會停下來,這和微控制器程式設計時一般將沒用的**空間填入jmp 0000語句是一樣地
nightwolf 網友提供:我遇見過,好像是在函式呼叫的時候引數入棧的問題。因為mfc的訊息使用巨集寫的,所以如果定義了onmessage()的函式,編譯能夠通過,但是呼叫一次後,堆疊指標發生了偏移。然後就。。。
vc工程的debug 和release
vc工程的debug 和release 今天早晨發現昨天提交到伺服器的windows版本編譯出了問題,經檢查,問題出在release版本的生成上。於是發現自己的疏忽,在配置vcproj檔案時,只修改了工程的debug狀態下的配置資訊,而沒有配置release的版本。general output di...
vc中release和debug的區別
debug和release 版本差異及除錯相關問題 i.記憶體分配問題 1.變數未初始化。下面的程式在debug中執行的很好。thing search thing something bool found for int i 0 i whatever.getsize i if found retur...
簡介vc中的release和debug版本的區別
debug通常稱為除錯版本,它包含除錯資訊,並且不作任何優化,便於程式設計師除錯程式。release稱為發布版本,它往往是進行了各種優化,使得程式在 大小和執行速度上都是最優的,以便使用者很好地使用。debug 和 release 的真正秘密,在於一組編譯選項。下面列出了分別針對二者的選項 當然除此...