1. 程式人生 > >VC運行庫版本不同導致鏈接.LIB靜態庫時發生重復定義問題的一個案例分析和總結

VC運行庫版本不同導致鏈接.LIB靜態庫時發生重復定義問題的一個案例分析和總結

修改 borde 並且 release 鏈接 部分 sdn 托管代碼 兩個

MSDN中對於在不同的配置下Link的LIB作了說明:

C Runtime Library

開關

對應的庫

版本

/MD

MSVCRT.LIB

多線程DLL的Release版本

/MDd

MSVCRTD.LIB

多線程DLL的Debug版本

/MT

LIBCMT.LIB

多線程靜態鏈接的Release版本

/MTd

LIBCMTD.LIB

多線程靜態鏈接的Debug版本

/clr

MSVCMRT.LIB

托管代碼和非托管代碼混合

/clr:pure

MSVCURT.LIB

純托管代碼

C++ Standard Library

開關

對應的庫

版本

/MD

MSVCPRT.LIB

多線程DLL的Release版本

/MDd

MSVCPRTD.LIB

多線程DLL的Debug版本

/MT

LIBCPMT.LIB

多線程靜態鏈接的Release版本

/MTd

LIBCPMTD.LIB

多線程靜態鏈接的Debug版本

編譯器會自動根據編譯選項,選擇對應的LIB文件。一般情況下這不會出現問題。

然而,在部分情況下,一旦你的程序的各個部分(LIB, OBJ…)並非由相同的編譯選項編譯出,而Link在一起的話,會出現各種各樣的看似很難解決的問題,這類問題主要以重復定義的錯誤形式存在,通常的解決方法也很簡單,就是選擇同樣的編譯選項進行編譯之後再Link。

......................

  1. 錯誤來源主要是重復定義的問題,而且重復定義的基本上都是VC Runtime和Standard C++ Library中的函數
  2. LIBCMT和LIBCPMT為Release下的Lib,本來不應該出現在Debug版本的鏈接的Lib中
  3. 重復定義的問題主要出現在:LIBCMT, LIBCPMT, MSVCPRTD, MSVCRTD

來看看出問題的LIB是那些:

  1. LIBCMT:C Runtime庫的多線程靜態鏈接的Release版本
  2. LIBCPMT:C++ Standard Library的多線程靜態鏈接的Release版本
  3. MSVCPRTD:C++ Standard Library的多線程DLL的Debug版本
  4. MSVCRTD:C Runtime Library的多線程DLL的Debug版本

當前我們的配置是多線程DLL的Debug版,因此3和4是應該出現在link的列表中的,不屬於多余。而後兩者則是只是當多線程靜態鏈接Release版中才會出現。這提示我在項目中加入的ANTLR.LIB可能是造成這個問題的根源,因為靜態庫的編譯選項很容易和主程序發生沖突,並且根據實際信息我們可以看出ANTLR.LIB應該是用多線程靜態鏈接的Release版本來編譯的。

這樣,解決方法就很清楚了:

  1. 切換到Release,因為ANTLR.LIB是在Release下面編譯的
  2. 把Run Time庫的版本修改成多線程靜態鏈接

做了這兩個修改之後編譯通過。

還有一種方法是,自己用多線程DLL的Debug版重新編譯一次ANTLR,生成一個新的ANTLRD.LIB,再link這個Lib也可以解決這個問題。

Summary

  1. 知道各個不同的LIB代表的版本信息非常重要,可以幫助快速定位問題
  2. 在編程的時候,一定要把所有的項目的編譯選項(是靜態鏈接Runtime庫還是動態鏈接Runtime庫,Debug/Release)配置成一樣的。如果部分LIB/OBJ是由第三方提供(OBJ情況很少見),一般情況下只能調整自己的編譯選項,除非你可以要求第三方提供其他版本的編譯好的LIB
  3. 在發布可重用的靜態LIB庫供其他人調用的時候,最好對應不同的編譯選項,乃至VC版本,提供不同版本的LIB。VC自己的Runtime就是最好的例子。

VC運行庫版本不同導致鏈接.LIB靜態庫時發生重復定義問題的一個案例分析和總結