Error hnk2005:exist already defined in msvcrt.lib(MSVCR100.dll)_LIBCMTD.lib 解決方案


今天在調試發布一個Windows 8游戲版本時發現這個異常:

Error    1 : error LNK2005: _exit already defined in msvcrt.lib(MSVCR100.dll)    LIBCMTD.lib    SampleGame

剛開始在開發Debug時並沒有出現過這樣問題.當嘗試發布一個新版本.構建Realse 包時.於是乎就超過75個 Lnk2005 Error出現List中:

2013-01-23_152751

 

ok.這樣瞬間就爆發了75個基本類同的錯誤.首先看了MS官方對這個錯誤定義:Linker Tools Error LNK2005.可見LNK在C++編程時常見的.一個重復定義的錯誤.那么總結一下官方針對這個Error定義出現的三種情況如下:

A:頭文件重復包含.

在頭文件中常常包含具有變量 函數 和類定義的. 但是問題是如果頭文件在相關宏等相關的重復鏈接處理措施.就會到時重復引用.

B:重復定義全局變量

這個應該就不用多說了.全局變量時針對整個工程的 .正確做法應該在一個Cpp文件中定義.類似:

   1:  int test_datatag

那么使用調用的方法就應該為:

   1:  extern int test_datatag

如果還繼續使用test_datatag則會立即爆出異常:

ObjError LNK2005 in index.cpp test_datatag already defined in index.obj

C:引用第三方庫.

這種情況比較普遍.主要是因為C Run time 函數庫和MFC庫存在沖突照成的.在目前的VC對C Runtime 運行時庫總共有6種:

Single-threaded (libc.lib) libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Multithreaded (libcmt.lib) libc.lib, msvcrt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Multithreaded using DLL (msvcrt.lib) libc.lib, libcmt.lib, libcd.lib, libcmtd.lib, msvcrtd.lib
Debug Single-threaded (libcd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcmtd.lib, msvcrtd.lib
Debug Multithreaded (libcmtd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, msvcrtd.lib
Debug Multithreaded using DLL (msvcrtd.lib) libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, libcmtd.lib

如果我們項目中引用不同的C函數庫. 微軟針對C有兩種C函數庫.一種是普通的函數庫:LIBC.LIB.格式/.特點是不支持多線程.另外一種是支持多線程的MSVCRT.lib.如果在一個工程中混合使用這兩種函數庫.則很容易導致LNK2005錯誤.一般情況下不推薦混合使用.如果真的有實際需求.最好處理方式采用MFC先C run time函數庫link鏈接.因此推薦使用支持多線程的msvcrt.lib.

C run time 運行時函數包如下庫:

2013-01-23_205728

當引用第三方庫時很容易出現這種錯誤.例如boot和WXWindow使用MD來編譯.也就是上面提到支持多線程的C runtime 函數庫.這時如果我們編輯自己項目沒有指明/MD 來編譯.就會導致兩種C函數出現沖突.並且在編譯時導致大量的LNK2005錯誤.

來看一下關於C run time 函數庫編譯形式常用如下:

2013-01-23_205842

說到這大概明白項目在Realse時大批量出現Error LNK2005原因.也就是因為引用庫導致的.現在看看目前項目中C/C++編譯設置: 打開項目在Properties->C/C++->All Options中找到Runtime Libraty值

2013-01-23_210230

可見為MD.

so.說了這么多搞清楚問題所在.如果Fix這個問題.

根據官方對着這個問題提出解決方案如下:

首先打開項目Properties->Configuration Properties->Linker中如果我們引用會看到對應的庫會看到對應的值:

2013-01-23_210833

這個問題是因為兩個庫之間存在沖突引起,.的.可以發現沖突出現LIBCMD.lib中.官方給出做法也相當的簡單直接.可以再項目直接忽略對該函數庫的引用:可以Ignore Specific Libraies設置對應的值:

2013-01-23_211159

設置保存后.重寫Rebuild 項目.發現所有錯誤全部沒有了.只是存在一定警告.,編譯完全通過.當然這種方式雖然簡單但顯得比較粗暴.因為libcmtd 這個庫有時候不能忽略,忽略后會有不能解析的外部符號錯誤.會導致有些運行時Run time 異常拋出.整個應用程序crash掉.

當然這種方式依然無法排除另外一種情況.

當C運行時[CRT]庫和MS基礎類MFC庫鏈接、順序有誤是.同樣也會導致LNK2005錯誤.主要是因為CRT庫對new、Delete、DllMain函數使用弱外部鏈接方式.MFC庫也包含了new、Delete、DllMain函數定義.這些函數要求先鏈接MFC庫然后再鏈接CRT庫.

完整解決方式采用強制鏈接器做法按照正確順序鏈接.通過在Properties-Configuration Properties->Linker->Command Line設置參數: /FORCE:MULTIPLE -關於該操作操作請參考官方文檔 Force Multiple

2013-01-23_212412

其實問題關鍵在於兩遍引用庫在進行編譯時設置必須相同才能REalse正常引用.當然相對更簡單的方式.逐個對引用項目進行對應Md編譯.然后重新添加Linker鏈接關系.這種方法雖然耗時但解決問題最為直接.也算是比較快捷方式之一.

設置完成發現項目正常編譯通過.

參考資料:

C Run Time  Libraries

/MD, /ML, /MT, /LD (Use Run-Time Library)

error LNK2005: _exit already defined in msvcrt.lib(MSVCR90.dll)_LIBCMTD.lib_

error LNK2005: xxx already defined in MSVCRT.lib(MSVCR100.dll) C:\something\LIBCMT.lib(setlocal.obj)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM