Microsoft Visual C++ 是微軟公司Visual Studio 開發套件中的一出重頭戲與前一個版本相比其革新性的集成開發環境與C++編譯器帶來了有許多改變在本文中主要講解程序員在升級程序時可能會遇到的一些不同之處及變化而這些變化很可能會使老一點的程序不能通過編譯總之這些變化絕不是偶然發生的其背後都有強大的理論依據在支撐所以使用Visual C++的程序員在升級之前一定要弄清楚這些變化
Visual C++中已經發生的變化
微軟Visual C++工作小組在對其產品作出修改之前已經過充分的考慮同時也顧及到了這些改變會對以前的代碼造成的影響雖然如此但有以下理由支持在新版本中作出的這些改變
Visual C++ 其中一個最重要之處就是更加遵循ISO C++標准可更好地跨平台移植代碼或集成進其他工具中如聲明在for循環中的變量生命期及變量類型現在也遵循C++標准了而且在默認設置中就是遵循ISO C++標准的正是因為此在一些老代碼中過去可行的一些方法現在可能要作出必要的修改才能通過編譯了
在這幾年中安全性是一個熱門的話題而且在將來也會得來越來越多的重視C++語言賦於了程序員無所不能的能力但凡事總有兩面性為減少代碼中的安全問題也為減少代碼中錯誤產生的可能性Visual C++ 作出了一系列的改變首先引入了安全CRT及不推薦使用的非安全API等概念而且在默認狀態下Visual C++ 也會進行代碼安全檢查
Visual C++ 增強了適用性這也使得可更方便地升級本身的二進制代碼成為可能而且也更加容易進行產品的漏洞修補
可維護性也是一個促進Visual C++變化的原因之一例如低價值的功能已經從產品中消失以減少在將來維護它們的可能性一個例子就是Visual Studio 中已經移除了單線程CRT因為已經不再需要它了以前為維護單線程CRT所花費的時間現在可以用在更重要的事情上了
最後其中的某些變化是為了增強Visual C++編譯器的可靠性為達此目的微軟公司此次保證了Visual C++中有明確定義並一致的行為
當然也要避免某些變化此次Visual C++的大多數變化都是在代碼安全層面上如果這些變化向後影響到二進制代碼的兼容性那麼就會盡量避免因為源代碼兼容性總是在二進制代碼兼容性之前被發現的另外如果某些變化致使人們不想采用或升級到版那麼這種變化也要避免因為這會導致軟件項目的總成本增加最後編寫代碼方式的改變也要在成本上證明是值得的否則就沒有必要去實現它了
Visual C++庫的十項突破性變化
Visual C++ 庫已經發生了一系列的變化可能會對現有的程序有所影響在升級到Visual C++ 之前必須要確定程序中沒有這些問題
參數的有效性
在C運行時庫中加入了一些代碼以檢查參數的有效性例如如果傳遞的目標緩沖區大小不足以strcpy使用通常這是在冒安全風險而新版本此時則會調用一個非法參數處理程序在release版中會調用DrWatson而在debug版中會產生斷言(assert)當然只要程序中傳遞的參數都是有效的就不會有什麼問題了
對非安全API的警告
在Visual C++ 中CRT中的一組函數已不再建議使用而應使用新提供的安全版本大多數這些不建議使用的函數如果使用不當將會導致緩沖區溢出或其他安全問題這些函數如strcpystrcat等等這些函數新的安全版本都在函數名後加了一個_s後綴以方便識別如strcpy_swcscpy_smbscpy_scalloc_s和strcat_s這些函數
如果想繼續使用老版本非安全的函數可在源代碼開始處加上#define value of _CRT_SECURE_NO_DEPRECATE(此處value代表某一數值)然而還是建議大家升級代碼使用新的安全函數
迭代器越界
受檢查的迭代器(checked iterators)和調試迭代器(debug iterators)也因為安全的原因進行了相應的更新如果迭代器越界則相應會調用一個非法參數處理程序
再次提醒可以通過拋出一個越界異常來避免產生非法參數問題在代碼中加入#define value of _SECURE_SCL_THROWS並把value值設為這樣就不會調用非法參數處理程序而是產生一個異常了
也可以通過設置#defined value of _SECURE_SCL值為零關閉此迭代器檢查通常默認情況下此選項是打開的
time_t類型
time_t類型通常用於顯示從年開始以來的秒數直到Visual C++ (即Visual C++ )time_t類型都被定義為一個long而到了Visual C++ 中已被定義為一個位類型可用於顯示一直到年的時間了
鏈接到CRT
托管應用程序現在不能靜態鏈接到CRT以往在Visual C++ 和中(指Visual Studio NET 與)可以生成靜態鏈接到CRT的CLR程序而在Visual Studio 卻行不通
單線程CRT支持
在Visual Studio 中已經取消了單線程CRT支持而且用發展的眼光來看未來大多數的人還是願意使用線程安全的多線程代碼
在線程中可使用_nolock後綴來優化代碼但同時這些函數是非線程安全的
異常處理
有兩種類型的異常處理可供選擇/EHa(異步的)和/EHs(同步C++異常)在以前如果使用了/EHs那麼在一個catch(…)塊中也許可能也許不可能捕捉到結構化異常因為此行為是沒有定義且不可靠的現在再使用/EHs時就可保證不會捕捉到結構化異常如果想與以前版本的Visual C++保持一致並且捕捉異步結構化異常還是應該在編譯時使用/EHa
初始化順序
以往如果代碼中同時有托管與本地全局變量及對象那麼初始化順序是不確定的如代碼中存在托管對象與本地對象互操作就不能保證哪一個對象先初始化了現在Visual Stuio 可保證所有的本地全局變量及對象先初始化然後才初始化托管全局變量及對象
printf
就目前來說printf中的%n格式化指示符一般用於指定輸出的字符個數這已經確認為一個安全隱患並且已禁用但可以使用set_printf_count_output來啟用它通過傳遞給set_printf_count_output一個零值()可禁用它而傳遞任意一個其他值可再次啟用
swprintf函數
為與C++標准保持一致對swprintf函數也作了修改現在它已遵循C++標准了在C++中通過適當的參數可實現重載這個函數的老版本已不再建議使用因為在C中是不允許重載的因此如果使用老格式將會返回一個錯誤
編譯器中的突破性變化
除了那些會影響到庫的變化之外也有一些變化會影響到編譯器以下是Visual C++ 中編譯器的主要變化需再次提醒的是此處並沒有列出所有的變化但卻是微軟公司VC++使用者及內部合作者所確認的關鍵性變化
指向成員的指針
在之前的版本中一個指向成員的指針不需使用取址操作符(&)就能獲取現在Visual C++ 已經嚴格按照標准必須要使用取址操作符這也有助於消除潛在的運行時錯誤但也導致了MFC庫的許多地方需要修改同時意味著可能會對現有的程序造成影響
范圍限制規則
在for循環聲明中默認情況下不強制執行范圍限制規則在之前的版本中for循環中變量的生命期將會延續到循環之外為與標准兼容for循環中定義的變量現在只限定在for循環內使用
wchar_t類型
現在wchar_t已為默認內置類型這就是說也許在以前wchar_t可能會被當作一個unsigned short因為它還不是內置類型所以當與那些有wchar_t類型變量的文件作符號比較時很可能會導致問題在Visual C++ 中wchar_t已是一個內置類型也就是說需要確定以前對wchar_t的用法不會導致轉譯為一個unsigned short
異常處理
為了與庫的變化保持一致編譯器已作了一些修改以便不會捕捉到結構化異常所以為與以前代碼保持兼容還是應該使用/EHa
參數屬性
為了提供更健壯的屬性也是為了代碼的健壯性編譯器現在將會檢查類型枚舉等等的屬性這意味著以前的代碼可能會在屬性方面碰到一個從未有過的編譯器錯誤
默認為int
為遵循C++標准對沒有類型聲明的變量或函數已不再默認為int類型但在C語言中仍然可以C++語言中已不行這甚至也影響到了微軟公司自身的代碼包括NT系統的代碼所以最好的方式還是顯式聲明
關於C的托管代碼
C語言編譯器一般不可能創建CLR的托管代碼因為C語言不是面向對象的它不符合CLR所使用的模型因此任何以C語言來編譯的代碼都會與CLR編譯器設置沖突例如如果在編譯時使用/TC設置而且又設置了CLR就會導致沖突
面向CLR的新語法
通過設置/clr編譯選項C++編譯器只接受新語法這將強制推廣加入到Visual C++ 中的新語法同時也會廢棄掉老代碼
安全檢查
在安全越來越得到重視的今天安全檢查選項/GS在默認情況下就是打開的還是有一定道理的在Visual C++ 中默認情況下將會使用/GS選項
結論
本文列出了微軟公司已確認的Visual C++ 中的一些關鍵性變化雖然不是所有的變化也不是最有可能沖擊到代碼的變化但此處所列出的項目將最有可能導致問題的產生
歸根結底在升級或用新版編譯器對程序作修改之前必須先試著編譯現有程序以確認代碼能通過編譯否則就不可避免要動手修正源代碼中存在的問題
From:http://tw.wingwit.com/Article/program/net/201311/11300.html