隨筆-17  評論-64  文章-79  trackbacks-1

          調(diào)試 Release 版本應(yīng)用程序

          引言

          如果在您的開發(fā)過程中遇到了常見的錯誤,或許您的 Release 版本不能正常運(yùn)行而 Debug 版本運(yùn)行無誤,那么我推薦您閱讀本文:因為并非如您想象的那樣, Release 版本可以保證您的應(yīng)用程序可以象 Debug 版本一樣運(yùn)行。

          如果您在開發(fā)階段完成之后或者在開發(fā)進(jìn)行一段時間之內(nèi)從來沒有進(jìn)行過 Release 版本測試,然而當(dāng)您測試的時候卻發(fā)現(xiàn)問題,那么請看我們的調(diào)試規(guī)則 1:

          規(guī)則 1 : 經(jīng)常性對開發(fā)軟件進(jìn)行 Debug Release 版本的常規(guī)測試 .

          測試 Release 版本的時間間隔越長,排除問題的難度越大,至少對 Release 版本進(jìn)行每周 1 次的測試,可以使您在緊湊的開發(fā)周期內(nèi)節(jié)省潛在的排故時間 .

          不要隨意刪除 Release 版本需要的代碼

          這點(diǎn)看起來似乎再明顯不過,但卻是開發(fā)人員無意中經(jīng)常犯的錯誤,原因在于編譯器編譯 Release 版本時候會主動排除在代碼中存在的宏,例如 ASSERT TRACE Release 版本會自動排除,這樣導(dǎo)致的問題是您在這些宏當(dāng)中運(yùn)行的代碼也被隨之刪除,這是非常危險的事情 J , 例如:

          ????? ASSERT ( m_ImageList . Create ( MAKEINTRESOURCE ( IDB_IMAGES ), 16, 1, RGB (255,255,255)));

          這樣的代碼在 Debug 模式不會出錯,圖像列表也自動創(chuàng)建了,然而在 Release 版本呢?后繼使用 m_ImageList 對象只會造成程序的 Crash! ,因此 ASSERT 宏中盡量使用邏輯運(yùn)算符作為驗證。

          規(guī)則 2 : 不要將代碼放置在僅在某種編譯選項中執(zhí)行的地方,對于使用 _DEBUG 等編譯選項宏內(nèi)部的代碼必須不影響整個程序的使用 .

          規(guī)則 3 : 不要使用規(guī)則 2 作為評判標(biāo)準(zhǔn)來刪除 ASSERT 宏, ASSERT 宏是個有用的工具,但容易使用錯誤 .

          使 Debug 編譯模式接近 Release 模式

          如果您的 Release 版本存在的問題是由代碼被編譯器自動排除造成的,那么通過這個方法您的問題可能會重現(xiàn) .

          一些問題的產(chǎn)生可能是由于不同編譯選項之間預(yù)定義符號造成的,因此您可以更改編譯模式下的預(yù)定義符號,從而使您的 Debug 模式接近 Release 模式,觀察錯誤是否產(chǎn)生,更改編譯預(yù)定義符號方法如下 :

          • Alt-F7

          打開項目設(shè)置,在 C++/C 頁面,選擇 "General" 類別,更改 "_DEBUG" 符號為 "NDEBUG".

        1. C++/C 頁面 , 選擇 "Preprocessor" 類別,添加預(yù)定義符號 "_DEBUG" "Undefined Symbols" .
        2. 使用 "Rebuild All" 重新編譯

          如果通過上面設(shè)置,您在 Release 編譯模式下面的問題在 Debug 模式下重現(xiàn),那么請您依據(jù)以下步驟對您的代碼進(jìn)行修改 :

          • 查找 ASSERT 排除其中的所有重要執(zhí)行語句,或者將 ASSERT 修改為 VERIFY .
          • 檢查 "#ifdef _DEBUG" 內(nèi)所有代碼,排除 Release 模式使用的代碼 .
          • 查找 TRACE 排除其中的所有重要執(zhí)行語句 . TRACE ASSERT 一樣,僅在 Debug 模式下編譯 .

          如果通過上面修改更正了您在 Debug 模式下的問題,那么您可以重新編譯 Release 模式,非常有可能您可以解決先前存在的問題! .

          錯誤的假定造成編譯模式錯誤

          您是否經(jīng)常性的假定您的變量或者對象被初試化成某個指定的值 ( 可能 0) ?您是否假定你所有關(guān)聯(lián)到的資源在應(yīng)用程序中都存在?這些也是 Debug Release 模式下不同問題產(chǎn)生的原因 .

          規(guī)則 4 : 除非您在代碼中對變量進(jìn)行初始化,否則不能作出如上假定 . 包括全局變量,自動變量,申請對象和 new 對象 .

          這種情況還常常發(fā)生在內(nèi)存順序的問題,記得原來使用結(jié)構(gòu)體的時候為了使用方便,比較兩個結(jié)構(gòu)體對象使用 memcmp ,在 Debug 版本工作正常,而 Release 版本計算出錯誤的解,看來的確不能進(jìn)行錯誤的假定!

          規(guī)則 5 : 確保刪除資源的所有引用都被刪除,例如 resource.h

        3. 軟件開發(fā)中,不同編譯版本對變量和內(nèi)存的初始化是不同的 . 如果您假定變量初始化為 0, 那么在 Win9x 系統(tǒng)的 Release 模式下,會出現(xiàn)異常現(xiàn)象。因此對所有變量,內(nèi)存顯式清 0 是較為安全的做法 .

        4. 如果您引用了已經(jīng)被刪除的資源,您的 Debug 版本可以正常工作,但是 Release 版本可能會 crash.

          您是否相信編譯器 ?

          編譯器警告級別和編譯噪音有著相當(dāng)大的關(guān)系 .

          通過提高編譯器警告級別可增加程序隱藏問題暴露的機(jī)會 . 通常設(shè)置警告級別在 "Level 3" 或者 "Level 4". 編譯并解決所有警告,這是發(fā)布 Release 版本應(yīng)用程序的一個很好的建議 . 這能暴露會使您的應(yīng)用程序出現(xiàn)問題的很多初始化問題和其它潛在的錯誤 .

          規(guī)則 6 : 開始項目之前先將編譯警告級別設(shè)置在 "Level 3" 或者 "Level 4" ,登記代碼之前確保消滅所有警告! .

          總結(jié)報告

          編譯模式下的調(diào)試

          曾經(jīng)不止一次的聽到一些 VC 開發(fā)者說 Release 模式下面不能進(jìn)行調(diào)試,幸運(yùn)的是:通過相應(yīng)設(shè)置,可以在 Release 模式進(jìn)行調(diào)試,因此那只不過是一個以訛傳訛的荒謬說法而已 .

          規(guī)則 7 : 當(dāng)前面所有的方法都無效的時候,在 Release 模式下面進(jìn)行調(diào)試 .

          Release 模式可以進(jìn)行調(diào)試,第一步是打開符號表 :

          • Alt-F7 打開項目設(shè)置,在 C++/C 頁面,選擇 "General" 類,修改 Debug Info setting "Program Database".
          • "Link" 頁面,選擇 "Generate Debug Info".
          • "Rebuild All"

          這些設(shè)置將允許您在 Release 模式下保留符號表,您也可以同時考慮以下設(shè)置 :

          • 調(diào)試 Release 版本應(yīng)用程序,您可以關(guān)閉優(yōu)化選項 .
          • 如果在 Release 模式下面不能設(shè)置斷點(diǎn),添加指令 "__asm {int 3}" 可以是您的應(yīng)用程序在改行停止 ( 確定在發(fā)布應(yīng)用程序時候排除這些代碼 ).

          Release

        5. 模式進(jìn)行調(diào)試的幾個限制 .

          • 最大的問題在于您不能跟蹤到 MFC 函數(shù)內(nèi)部,原因在于 Release 版本的 MFC 動態(tài)鏈接庫不包含調(diào)試信息和符號表 .
          • 同上,想要調(diào)試調(diào)用的 dll ,您必須給它們?nèi)考由险{(diào)試信息和符號表 .

          編譯器生成了錯誤的代碼 ?

          或許有的時候您會發(fā)現(xiàn) VC++ 編譯器生成了 問題代碼 ,然而坦率的講,人們通常抱怨的太早 . 您可以在 Release 模式下面關(guān)閉優(yōu)化選項來進(jìn)行測試 .

          如果這個操作解決了您的問題,或許您的編碼習(xí)慣存在問題 . 信不信由你 , 極其可能在您的編碼中存在模棱兩可的求解或者看起來似乎正確,某些條件下也是正確的情況 . 舉個例子,下面的代碼在 Debug 模式似乎一切 正常 ,而在 Release 模式下面卻會出錯!

          						
          								
          										#include <stdio.h>
          								
          						
          				
          						
          								
          										?
          								
          						
          				
          						
          								
          										
          												
          														int
          												
          										
          										* func1()
          								
          						
          				
          						
          								{
          						
          				
          						
          								
          										
          												
          														int
          												
          										
          										 retval = 
          										
          												
          														5
          												
          										
          										;
          								
          						
          				
          						
          								
          										
          												
          														return
          												
          										
          										 &retval;
          								
          						
          				
          						
          								}
          						
          				
          						
          								
          										?
          								
          						
          				
          						
          								
          										
          												
          														int
          												
          										
          										 main(
          										
          												
          														int
          												
          										
          										 argc, 
          										
          												
          														char
          												
          										
          										* argv[])
          								
          						
          				
          						
          								{
          						
          				
          						
          								
          										printf(
          										
          												
          														"%d\n"
          												
          										
          										, *func1());
          								
          						
          				
          						
          								
          										
          												
          														return
          												
          										
          										
          										
          										
          												
          														0
          												
          										
          										;
          								
          						
          				
          						
          								}
          						
          				

          我相信大多數(shù)程序員尤其是初學(xué)者容易遇到此類情況的 .

          規(guī)則 8 : 如果關(guān)閉 Release 模式的優(yōu)化選項可以使您的應(yīng)用程序運(yùn)行正常,而打開優(yōu)化選項則出現(xiàn)問題的化,原因多半在于您的不良編碼習(xí)慣造成的 . 這意味著必須仔細(xì)檢查您的代碼,清理出那些錯誤的假設(shè),懸空指針等等 . 等同的這告訴您,在 Debug 模式和關(guān)閉優(yōu)化選項的 Release 模式下您的應(yīng)用程序工作正常全是因為系統(tǒng)隱含的運(yùn)氣,您必須著手更正存在隱患的代碼,否則在日后可能會造成巨大的損失 .

          規(guī)則 9 : 如果您已經(jīng)徹底檢查了您的代碼,并且沒有發(fā)現(xiàn)問題,那么您最好逐個打開優(yōu)化選項將產(chǎn)生錯誤的原因限制在某個范圍之內(nèi) .

          BTW- 以上問題代碼由 C++ 編譯器自動檢出 . 如果您已經(jīng)遵循 規(guī)則 6 您或許在前面環(huán)節(jié)中已經(jīng)解決了這些問題 .

        6. 憑我的開發(fā)經(jīng)驗,編譯器極少會產(chǎn)生錯誤的代碼(當(dāng)然要注意接口程序邊界對齊的問題) . 通常在使用模板類時候 VC6 編譯器或許會產(chǎn)生斷言 ASSERT 錯誤,這種情況您只需更新補(bǔ)丁即可解決 .

          最后的思考



          -->

          在日常編碼中只需稍微增加一點(diǎn)嚴(yán)格的檢測,便能有效的避免新的Debug -v- Release模式問題的產(chǎn)生,以下是我的一些經(jīng)驗.

          1.????? 取出(check out)需要修改的代碼.

          2.????? 修改代碼,排除所有警告,編譯DebugRelease版本.

          3.????? 詳細(xì)測試新代碼,即單步調(diào)試新代碼段之后進(jìn)入工作代碼,確保代碼無誤.

          4.????? 更正所有問題.

          5.????? 確認(rèn)無誤之后將新代碼登記入庫(check in).

          6.????? 對登記入庫的代碼進(jìn)行全新的編譯,確保新登記代碼與其它代碼融合.

          7.????? 重新詳細(xì)測試代碼.

          8.????? 更正新問題(或許可以發(fā)現(xiàn)登記入庫代碼存在的問題)

          嚴(yán)格按照以上步驟,您在設(shè)計開發(fā)過程中即可解決大量問題,避免在最后發(fā)布應(yīng)用程序時候產(chǎn)生新的難以定位的問題.

          后記

          本文是在我的開發(fā)歷程中遇到Release版本應(yīng)用程序發(fā)布,產(chǎn)生錯誤的時候苦苦求索得到的一些經(jīng)驗,原文來自于codeproject,經(jīng)過本人潤色,改寫成為適合國內(nèi)開發(fā)者的文章,希望能對大家有用,謝謝!

        7. posted on 2007-03-09 11:53 飛鳥 閱讀(486) 評論(0)  編輯  收藏 所屬分類: VC
          主站蜘蛛池模板: 扶绥县| 平泉县| 新巴尔虎右旗| 准格尔旗| 黔江区| 湟中县| 陆河县| 武陟县| 怀集县| 岑溪市| 安龙县| 冷水江市| 南华县| 泗洪县| 滨州市| 泾川县| 崇信县| 淮南市| 容城县| 泸定县| 邢台市| 龙海市| 得荣县| 公主岭市| 新源县| 临城县| 施甸县| 三江| 加查县| 思茅市| 鸡东县| 林芝县| 九江市| 上虞市| 和田县| 林甸县| 玉溪市| 清徐县| 十堰市| 达尔| 贵定县|