引言
若是在您的開發過程當中遇到了常見的錯誤,或許您的Release版本不能正常運行而Debug版本運行無誤,那麼我推薦您閱讀本文:由於並不是如您想象的那樣,Release版本能夠保證您的應用程序能夠象Debug版本同樣運行。
若是您在開發階段完成以後或者在開發進行一段時間以內歷來沒有進行過Release版本測試,然而當您測試的時候卻發現問題,那麼請看咱們的調試規則1:
規則1:
常常性對開發軟件進行Debug和Release版本的常規測試. 測試Release版本的時間間隔越長,排除問題的難度越大,至少對Release版本進行每週1次的測試,可使您在緊湊的開發週期內節省潛在的排故時間. 不要隨意刪除Release版本須要的代碼這點看起來彷佛再明顯不過,但倒是開發人員無心中常常犯的錯誤,緣由在於編譯器編譯Release版本時候會主動排除在代碼中存在的宏,例如ASSERT和TRACE在Release版本會自動排除,這樣致使的問題是您在這些宏當中運行的代碼也被隨之刪除,這是很是危險的事情J,例如: ASSERT(m_ImageList.Create(MAKEINTRESOURCE(IDB_IMAGES), 16, 1, RGB(255,255,255))); 這樣的代碼在Debug模式不會出錯,圖像列表也自動建立了,然而在Release版本呢?後繼使用m_ImageList對象只會形成程序的Crash!,所以ASSERT宏中儘可能使用邏輯運算符做爲驗證。
規則 2:
不要將代碼放置在僅在某種編譯選項中執行的地方,對於使用_DEBUG等編譯選項宏內部的代碼必須不影響整個程序的使用。
規則 3:
不要使用規則2做爲評判標準來刪除ASSERT宏,ASSERT宏是個有用的工具,但容易使用錯誤. 使Debug編譯模式接近Release模式若是您的Release版本存在的問題是由代碼被編譯器自動排除形成的,那麼經過這個方法您的問題可能會重現. 一些問題的產生多是因爲不一樣編譯選項之間預約義符號形成的,所以您能夠更改編譯模式下的預約義符號,從而使您的Debug模式接近Release模式,觀察錯誤是否產生,更改編譯預約義符號方法以下: a.. Alt-F7打開項目設置,在C++/C 頁面,選擇"General"類別,更改"_DEBUG"符號爲"NDEBUG". b.. 在C++/C 頁面, 選擇"Preprocessor"類別,添加預約義符號"_DEBUG"到"Undefined Symbols"欄. c.. 使用"Rebuild All"從新編譯若是經過上面設置,您在Release編譯模式下面的問題在Debug模式下重現,那麼請您依據如下步驟對您的代碼進行修改: a.. 查找ASSERT排除其中的全部重要執行語句,或者將ASSERT修改成VERIFY. b.. 檢查"#ifdef _DEBUG" 內全部代碼,排除Release模式使用的代碼. c.. 查找TRACE 排除其中的全部重要執行語句. TRACE和ASSERT同樣,僅在Debug模式下編譯. 若是經過上面修改更正了您在Debug模式下的問題,那麼您能夠從新編譯Release模式,很是有可能您能夠解決先前存在的問題!. 錯誤的假定形成編譯模式錯誤您是否常常性的假定您的變量或者對象被初試化成某個指定的值(可能0)?您是否假定你全部關聯到的資源在應用程序中都存在?這些也是Debug和Release模式下不一樣問題產生的緣由。
規則 4:
除非您在代碼中對變量進行初始化,不然不能做出如上假定. 包括全局變量,自動變量,申請對象和new對象. 這種狀況還經常發生在內存順序的問題,記得原來使用結構體的時候爲了使用方便,比較兩個結構體對象使用memcmp,在Debug版本工做正常,而Release版本計算出錯誤的解,看來的確不能進行錯誤的假定!
規則 5:
確保刪除資源的全部引用都被刪除,例如resource.h中的定義. 軟件開發中,不一樣編譯版本對變量和內存的初始化是不一樣的. 若是您假定變量初始化爲0,那麼在Win9x系統的Release模式下,會出現異常現象。所以對全部變量,內存顯式清0是較爲安全的作法. 若是您引用了已經被刪除的資源,您的Debug版本能夠正常工做,可是Release版本可能會crash. 您是否相信編譯器? 編譯器警告級別和編譯噪音有着至關大的關係. 經過提升編譯器警告級別可增長程序隱藏問題暴露的機會.一般設置警告級別在"Level 3"或者 "Level 4".編譯並解決全部警告,這是發佈Release版本應用程序的一個很好的建議.這能暴露會使您的應用程序出現問題的不少初始化問題和其它潛在的錯誤.
規則 6:
開始項目以前先將編譯警告級別設置在"Level 3" 或者 "Level 4" ,登記代碼以前確保消滅全部警告!. 總結報告編譯模式下的調試曾經不止一次的聽到一些VC開發者說Release模式下面不能進行調試,幸運的是:經過相應設置,能夠在Release模式進行調試,所以那隻不過是一個以訛傳訛的荒謬說法而已。
規則 7:
當前面全部的方法都無效的時候,在Release模式下面進行調試. Release模式能夠進行調試,第一步是打開符號表: a.. Alt-F7打開項目設置,在C++/C 頁面,選擇"General"類,修改Debug Info setting 爲 "Program Database". b.. 在"Link" 頁面,選擇"Generate Debug Info". c.. "Rebuild All" 這些設置將容許您在Release模式下保留符號表,您也能夠同時考慮如下設置: a.. 調試Release版本應用程序,您能夠關閉優化選項. b.. 若是在Release模式下面不能設置斷點,添加指令"__asm {int 3}" 可使您的應用程序在該行中止(肯定在發佈應用程序時候排除這些代碼). 在Release模式進行調試的幾個限制. a.. 最大的問題在於您不能跟蹤到MFC函數內部,緣由在於Release版本的MFC動態連接庫不包含調試信息和符號表. b.. 同上,想要調試調用的dll,您必須給它們所有加上調試信息和符號表. 編譯器生成了錯誤的代碼? 或許有的時候您會發現VC++編譯器生成了’問題代碼’,然而坦率的講,人們一般抱怨的太早.您能夠在Release模式下面關閉優化選項來進行測試. 若是這個操做解決了您的問題,或許您的編碼習慣存在問題. 信不信由你, 極其可能在您的編碼中存在模棱兩可的求解或者看起來彷佛正確,某些條件下也是正確的狀況. 舉個例子,下面的代碼在Debug模式彷佛一切’正常’,而在Release模式下面卻會出錯! #include int* func1(){int retval = 5;return &retval;} int main(int argc, char* argv[]){printf("%d/n", *func1());return 0;}我相信大多數程序員尤爲是初學者容易遇到此類狀況的。
規則 8:
若是關閉Release模式的優化選項可使您的應用程序運行正常,而打開優化選項則出現問題的化,緣由多半在於您的不良編碼習慣形成的. 這意味着必須仔細檢查您的代碼,清理出那些錯誤的假設,懸空指針等等. 等同的這告訴您,在Debug模式和關閉優化選項的Release模式下您的應用程序工做正常全是由於系統隱含的運氣,您必須着手更正存在隱患的代碼,不然在往後可能會形成巨大的損失。
規則 9:
若是您已經完全檢查了您的代碼,而且沒有發現問題,那麼您最好逐個打開優化選項將產生錯誤的緣由限制在某個範圍以內. BTW- 以上問題代碼由C++編譯器自動檢出. 若是您已經遵循 規則 6 您或許在前面環節中已經解決了這些問題. 憑個人開發經驗,編譯器極少會產生錯誤的代碼(固然要注意接口程序邊界對齊的問題).一般在使用模板類時候VC6編譯器或許會產生斷言ASSERT錯誤,這種狀況您只需更新補丁便可解決。
最後的思考在平常編碼中只需稍微增長一點嚴格的檢測,便能有效的避免新的Debug -v- Release模式問題的產生,如下是個人一些經驗。
1. 取出(check out)須要修改的代碼。
2. 修改代碼,排除全部警告,編譯Debug和Release版本.
3. 詳細測試新代碼,即單步調試新代碼段以後進入工做代碼,確保代碼無誤.
4. 更正全部問題.
5. 確認無誤以後將新代碼登記入庫(check in).
6. 對登記入庫的代碼進行全新的編譯,確保新登記代碼與其它代碼融合.
7. 從新詳細測試代碼.
8. 更正新問題(或許能夠發現登記入庫代碼存在的問題) 嚴格按照以上步驟,您在設計開發過程當中便可解決大量問題,避免在最後發佈應用程序時候產生新的難以定位的問題.
後記本文是在個人開發歷程中遇到Release版本應用程序發佈,產生錯誤的時候苦苦求索獲得的一些經驗,原文來自於codeproject,通過本人潤色,改寫成爲適合國內開發者的文章,但願能對你們有用,謝謝! 轉載: Debug版本包括調試信息,因此要比Release版本大不少(可能大數百K至數M)。至因而否須要DLL支持,主要看你採用的編譯選項。若是是基於ATL的,則Debug和Release版本對DLL的要求差很少。若是採用的編譯選項爲使用MFC動態庫,則須要MFC42D.DLL等庫支持,而Release版本須要MFC42.DLL支持。Release Build不對源代碼進行調試,不考慮MFC的診斷宏,使用的是MFC Release庫,編譯十對應用程序的速度進行優化,而Debug Build則正好相反,它容許對源代碼進行調試,能夠定義和使用MFC的診斷宏,採用MFC Debug庫,對速度沒有優化。
- 1、Debug 和 Release 編譯方式的本質區別 Debug 一般稱爲調試版本,它包含調試信息,而且不做任何優化,便於程序員調試程序。Release 稱爲發佈版本,它每每是進行了各類優化,使得程序在代碼大小和運行速度上都是最優的,以便用戶很好地使用。 Debug 和 Release 的真正祕密,在於一組編譯選項。下面列出了分別針對兩者的選項(固然除此以外還有其餘一些,如/Fd /Fo,但區別並不重要,一般他們也不會引發 Release 版錯誤,在此不討論) Debug 版本: /MDd /MLd 或 /MTd 使用 Debug runtime library(調試版本的運行時刻函數庫) /Od 關閉優化開關 /D "_DEBUG" 至關於 #define _DEBUG,打開編譯調試代碼開關(主要針對 assert函數) /ZI 建立 Edit and continue(編輯繼續)數據庫,這樣在調試過 程中若是修改了源代碼不需從新編譯 /GZ 能夠幫助捕獲內存錯誤 /Gm 打開最小化重連接開關,減小連接時間 Release 版本: /MD /ML 或 /MT 使用發佈版本的運行時刻函數庫 /O1 或 /O2 優化開關,使程序最小或最快 /D "NDEBUG" 關閉條件編譯調試代碼開關(即不編譯assert函數) /GF 合併重複的字符串,並將字符串常量放到只讀內存,防止 被修改 實際上,Debug 和 Release 並無本質的界限,他們只是一組編譯選項的集合,編譯器只是按照預約的選項行動。事實上,咱們甚至能夠修改這些選項,從而獲得優化過的調試版本或是帶跟蹤語句的發佈版本。
- 2、哪些狀況下 Release 版會出錯 有了上面的介紹,咱們再來逐個對照這些選項看看 Release 版錯誤是怎樣產生的 1. Runtime Library:連接哪一種運行時刻函數庫一般只對程序的性能產生影響。調試版本的 Runtime Library 包含了調試信息,並採用了一些保護機制以幫助發現錯誤,所以性能不如發佈版本。編譯器提供的 Runtime Library 一般很穩定,不會形成 Release 版錯誤;卻是因爲 Debug 的 Runtime Library 增強了對錯誤的檢測,如堆內存分配,有時會出現 Debug 有錯但 Release 正常的現象。應當指出的是,若是 Debug 有錯,即便 Release 正常,程序確定是有 Bug 的,只不過多是 Release 版的某次運行沒有表現出來而已。 2. 優化:這是形成錯誤的主要緣由,由於關閉優化時源程序基本上是直接翻譯的,而打開優化後編譯器會做出一系列假設。這類錯誤主要有如下幾種:
-
- (1) 幀指針(Frame Pointer)省略(簡稱 FPO ):在函數調用過程當中,全部調用信息(返回地址、參數)以及自動變量都是放在棧中的。若函數的聲明與實現不一樣(參數、返回值、調用方式),就會產生錯誤――――但 Debug 方式下,棧的訪問經過 EBP 寄存器保存的地址實現,若是沒有發生數組越界之類的錯誤(或是越界「很少」),函數一般能正常執行;Release 方式下,優化會省略 EBP 棧基址指針,這樣經過一個全局指針訪問棧就會形成返回地址錯誤是程序崩潰。C++ 的強類型特性能檢查出大多數這樣的錯誤,但若是用了強制類型轉換,就不行了。你能夠在 Release 版本中強制加入 /Oy- 編譯選項來關掉幀指針省略,以肯定是否此類錯誤。此類錯誤一般有: ● MFC 消息響應函數書寫錯誤。正確的應爲 afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam); ON_MESSAGE 宏包含強制類型轉換。防止這種錯誤的方法之一是重定義 ON_MESSAGE 宏,把下列代碼加到 stdafx.h 中(在#include "afxwin.h"以後),函數原形錯誤時編譯會報錯#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 告訴編譯器該變量可能被程序以外的未知方式修改(如系統、其餘進程和線程)。優化程序爲了使程序性能提升,常把一些變量放在寄存器中(相似於 register 關鍵字),而其餘進程只能對該變量所在的內存進行修改,而寄存器中的值沒變。若是你的程序是多線程的,或者你發現某個變量的值與預期的不符而你確信已正確的設置了,則極可能遇到這樣的問題。這種錯誤有時會表現爲程序在最快優化出錯而最小優化正常。把你認爲可疑的變量加上 volatile 試試。
-
- (3) 變量優化:優化程序會根據變量的使用狀況優化變量。例如,函數中有一個未被使用的變量,在 Debug 版中它有可能掩蓋一個數組越界,而在 Release 版中,這個變量極可能被優化調,此時數組越界會破壞棧中有用的數據。固然,實際的狀況會比這複雜得多。與此有關的錯誤有: ● 非法訪問,包括數組越界、指針錯誤等。例如 void fn(void) { int i; i = 1; int a[4]; { int j; j = 1; } a[-1] = 1;//固然錯誤不會這麼明顯,例以下標是變量 a[4] = 1; } j 雖然在數組越界時已出了做用域,但其空間並未收回,於是 i 和 j 就會掩蓋越界。而 Release 版因爲 i、j 並未其很大做用可能會被優化掉,從而使棧被破壞。 3. _DEBUG 與 NDEBUG :當定義了 _DEBUG 時,assert() 函數會被編譯,而 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() 。事實上,這些宏都是調用了 assert() 函數,只不過附加了一些與庫有關的調試代碼。若是你在這些宏中加入了任何程序代碼,而不僅是布爾表達式(例如賦值、能改變變量值的函數調用 等),那麼 Release 版都不會執行這些操做,從而形成錯誤。初學者很容易犯這類錯誤,查找的方法也很簡單,由於這些宏都已在上面列出,只要利用 VC++ 的 Find in Files 功能在工程全部文件中找到用這些宏的地方再一一檢查便可。另外,有些高手可能還會加入 #ifdef _DEBUG 之類的條件編譯,也要注意一下。 順便值得一提的是 VERIFY() 宏,這個宏容許你將程序代碼放在布爾表達式裏。這個宏一般用來檢查 Windows API 的返回值。有些人可能爲這個緣由而濫用 VERIFY() ,事實上這是危險的,由於 VERIFY() 違反了斷言的思想,不能使程序代碼和調試代碼徹底分離,最終可能會帶來不少麻煩。所以,專家們建議儘可能少用這個宏。 4. /GZ 選項:這個選項會作如下這些事 (1) 初始化內存和變量。包括用 0xCC 初始化全部自動變量,0xCD ( Cleared Data ) 初始化堆中分配的內存(即動態分配的內存,例如 new ),0xDD ( Dead Data ) 填充已被釋放的堆內存(例如 delete ),0xFD( deFencde Data ) 初始化受保護的內存(debug 版在動態分配內存的先後加入保護內存以防止越界訪問),其中括號中的詞是微軟建議的助記詞。這樣作的好處是這些值都很大,做爲指針是不可能的(並且 32 位系統中指針不多是奇數值,在有些系統中奇數的指針會產生運行時錯誤),做爲數值也不多遇到,並且這些值也很容易辨認,所以這頗有利於在 Debug 版中發現 Release 版纔會遇到的錯誤。要特別注意的是,不少人認爲編譯器會用 0 來初始化變量,這是錯誤的(並且這樣很不利於查找錯誤)。 (2) 經過函數指針調用函數時,會經過檢查棧指針驗證函數調用的匹配性。(防止原形不匹配) (3) 函數返回前檢查棧指針,確認未被修改。(防止越界訪問和原形不匹配,與第二項合在一塊兒可大體模擬幀指針省略 FPO ) 一般 /GZ 選項會形成 Debug 版出錯而 Release 版正常的現象,由於 Release 版中未初始化的變量是隨機的,這有可能使指針指向一個有效地址而掩蓋了非法訪問。 除此以外,/Gm /GF 等選項形成錯誤的狀況比較少,並且他們的效果顯而易見,比較容易發現。 在使用VC開發軟件的過程當中,正當要享受那種興奮的時候忽然發現: release與debug運行結果不一致,甚至出錯,而release又不方便調試,真的是當頭一棒啊,但是疼歸疼,問題總要解決,下面將講述一下個人兩點經驗,看看是否是其中之一: 1. 變量。你們都知道,debug跟release在初始化變量時所作的操做是不一樣的,debug是將每一個字節位都賦成0xcc,而release的賦值近似於隨機(我想是直接從內存中分配的,沒有初始化過,但debug爲何不是0xff或0x00或其餘什麼的就不得而知了)。這樣就明確了,若是你的程序中的某個變量沒被初始化就被引用,就頗有可能出現異常:用做控制變量將致使流程導向不一致;用做數組下標將會使程序崩潰;更加多是形成其餘變量的不許確而引發其餘的錯誤。因此在聲明變量後立刻對其初始化一個默認的值是最簡單有效的辦法,不然項目大了你找都沒地方找。代碼存在錯誤在debug方式下可能會忽略而不被察覺到,如debug方式下數組越界也大多不會出錯,在release中就暴露出來了,這個找起來就比較難了:( 仍是本身多加註意吧 2. 自定義消息的消息參數。 MFC爲咱們提供了很好的消息機制,更增長了自定義消息,好處我就不用多說了。這也存在debug跟release的問題嗎?答案是確定的。在自定義消息的函數體聲明時,時常會看到這樣的寫法:afx_msg LRESULT OnMessageOwn(); 當你在多線程或進程間使用了消息傳遞時就會致使無效句柄之類的錯誤。這個緣由就是消息體的參數沒有添加,即應該寫成:afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam); (具體緣由我也不太清楚,是否是由於調用時按着默認的參數多分配了WPARAM+LPARAM的空間而破壞了應用程序的內存空間?還請高手多指點) 避免的方法: 1. 注意變量的初始化 2. 自定義消息的標準寫法 3. 使用調試語句TRACE等時使用後最好註釋掉 4. 儘可能使用try - catch(...) VERIFY 和 ASSERT 的區別:一個在Release下面能夠執行,一個不能夠 DEBUG和RELEASE 版本差別及調試相關問題: 內存分配問題 1. 變量未初始化。下面的程序在debug中運行的很好。 thing * search(thing * something) BOOL found; for(int i = 0; i < whatever.GetSize(); i++) { if(whatever[i]->field == something->field) { /* found it */ found = TRUE; break; } /* found it */ } if(found) return whatever[i]; else return NULL; 而在release中卻不行,由於debug中會自動給變量初始化found=FALSE,而在release版中則不會。因此儘量的給變量、類或結構初始化。 2. 數據溢出的問題 如:char buffer[10]; int counter; lstrcpy(buffer, "abcdefghik"); 在debug版中buffer的NULL覆蓋了counter的高位,可是除非counter>16M,什麼問題也沒有。可是在release版中,counter可能被放在寄存器中,這樣NULL就覆蓋了buffer下面的空間,可能就是函數的返回地址,這將致使ACCESS ERROR。 3. DEBUG版和RELEASE版的內存分配方式是不一樣的 。若是你在DEBUG版中申請 ele 爲 6*sizeof(DWORD)=24bytes,實際上分配給你的是32bytes(debug版以32bytes爲單位分配), 而在release版,分配給你的就是24bytes(release版以8bytes爲單位),因此在debug版中若是你寫ele[6],可能不會有什麼問題,而在release版中,就有ACCESS VIOLATE。 II. ASSERT和VERIFY 1. ASSERT在Release版本中是不會被編譯的。 ASSERT宏是這樣定義的 #ifdef _DEBUG #define ASSERT(x) if( (x) == 0) report_assert_failure() #else #define ASSERT(x) #endif 實際上覆雜一些,但可有可無。假如你在這些語句中加了程序中必需要有的代碼 好比 ASSERT(pNewObj = new CMyClass); pNewObj->MyFunction(); 這種時候Release版本中的pNewObj不會分配到空間 因此執行到下一個語句的時候程序會報該程序執行了非法操做的錯誤。這時能夠用VERIFY : #ifdef _DEBUG #define VERIFY(x) if( (x) == 0) report_assert_failure() #else #define VERIFY(x) (x) #endif 這樣的話,代碼在release版中就能夠執行了。 III. 參數問題: 自定義消息的處理函數,必須定義以下: afx_msg LRESULT OnMyMessage(WPARAM, LPARAM); 返回值必須是HRESULT型,不然Debug會過,而Release出錯 IV. 內存分配 保證數據建立和清除的統一性:若是一個DLL提供一個可以建立數據的函數,那麼這個DLL同時應該提供一個函數銷燬這些數據。數據的建立和清除應該在同一個層次上。 V. DLL的災難 人們將不一樣版本DLL混合形成的不一致性形象的稱爲 「動態鏈接庫的地獄「(DLL Hell) ,甚至微軟本身也這麼說(http://msdn.microsoft.com/library/techart/dlldanger1.htm)。 若是你的程序使用你本身的DLL時請注意: 1.不能將debug和release版的DLL混合在一塊兒使用。debug都是debug版,release版都是release版。 解決辦法是將debug和release的程序分別放在主程序的debug和release目錄下 2.千萬不要覺得靜態鏈接庫會解決問題,那隻會使狀況更糟糕。 VI. RELEASE板中的調試 : 1.將ASSERT() 改成 VERIFY() 。找出定義在"#ifdef _DEBUG"中的代碼,若是在RELEASE版本中須要這些代碼請將他們移到定義外。查找TRACE(...)中代碼,由於這些代碼在RELEASE中也不被編譯。 請認真檢查那些在RELEASE中須要的代碼是否並無被便宜。 2.變量的初始化所帶來的不一樣,在不一樣的系統,或是在DEBUG/RELEASE版本間都存在這樣的差別,因此請對變量進行初始化。 3.是否在編譯時已經有了警告?請將警告級別設置爲3或4,而後保證在編譯時沒有警告出現. VII. 將Project Settings" 中 "C++/C " 項目下優化選項改成Disbale(Debug)。編譯器的優化可能致使許多意想不到的錯誤,請參考http://www.pgh.net/~newcomer/debug_release.htm 1.此外對RELEASE版本的軟件也能夠進行調試,請作以下改動: 在"Project Settings" 中 "C++/C " 項目下設置 "category" 爲 "General" 而且將"Debug Info"設置爲 "Program Database"。 在"Link"項目下選中"Generate Debug Info"檢查框。 "Rebuild All" 如此作法會產生的一些限制: 沒法得到在MFC DLL中的變量的值。 必須對該軟件所使用的全部DLL工程都進行改動。 另: MS BUG:MS的一份技術文檔中代表,在VC5中對於DLL的"Maximize Speed"優化選項並未被徹底支持,所以這將會引發內存錯誤並致使程序崩潰