程序同時使用微軟的多個C運行庫的風險

        同時使用微軟的多個C運行庫的風險

            

 Microsoft的Visual C++是Windows下使用最廣的編譯器,歷史悠久,目前的最新版本是VC2008。VC有多個版本,每個版本都附帶一個C運行庫。從VC6開始附帶的運行庫如下:

   VC6                     msvcrt.dll    

   VC7(VC 2002)     msvcrt7.dll

   VC7.1(VC2003)   msvcrt71.dll

   VC8(VC2005)      msvcrt80.dll

   VC9(VC2008)      msvcrt90.dll

msvcrt.dll後來由Windows自帶,成爲了Windows系統的一部分,描述也成了“Windows NT CRT DLL”。

 

假如一個程序在VC2008下面開發,但是它依賴於某些第三方動態庫,這些第三方庫由VC6編譯,這樣程序就會同時依賴於msvcrt.dll和msvcrt90.dll這兩個C運行庫。這樣做有什麼風險呢?程序中很多對象、資源都是由C運行庫維護的(那些不依賴於C運行庫的程序例外),比如內存(通過malloc申請的內存)、文件指針(FILE*)、環境變量。程序依賴多個C運行庫,進程中就有C運行庫的多個實例,這些個不同C運行庫維護的對象、資源是不能混用的,否則就會導致嚴重的錯誤。比如通過msvcrt.dll打開的文件指針傳遞給msvcr90.dll去讀取文件內容。

詳情可以參考下面的兩個文檔:

C Run-Time Libraries http://msdn.microsoft.com/en-us/library/abx4dbyh.aspx

Potential Errors Passing CRT Objects Across DLL Boundaries

http://msdn.microsoft.com/en-us/library/ms235460.aspx

這種情況一定會出問題嗎?那到不一定。如果動態庫的接口設計者注意到了這個問題,接口設計的比較合理,參數和返回值的類型都比較合理,就不會有問題。

 

另外一種情況與此類似,也會導致多個C運行庫實例的出現。那就是:程序中某些庫鏈接到了Debug版本的C運行庫,某些庫鏈接到了Release版本的C運行庫。

 

對於新版本的VC來說,如果打了補丁後C運行庫進行了更新,新的C運行庫和舊的也是不同的版本,即使它們名字相同,它們會被放到/WINDOWS/WinSxS下不同的目錄中。這種情況也需要謹慎小心,儘量使用同一個補丁版本進行編譯,鏈接到同樣版本的運行庫。

 

在程序有多個庫組成時,用同一個編譯器編譯,同時保證它們的編譯選項儘量一致。這樣避免一些莫名其妙錯誤的發生。

 

同樣這個問題在C++運行庫中也存在,不再詳述。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章