VC++的鏈接錯誤LNK2005 ?
? ?
? 編程中經(jīng)常能遇到LNK2005錯誤——重復(fù)定義錯誤,其實LNK2005錯誤并不是一個很難解決的錯誤。弄清楚它形成的原因,就可以輕松解決它了。 ?
? ?
? 造成LNK2005錯誤主要有以下幾種情況: ?
? 1.重復(fù)定義全局變量。可能存在兩種情況: ?
? A、對于一些初學(xué)編程的程序員,有時候會以為需要使用全局變量的地方就可以使用定義申明一下。其實這是錯誤的,全局變量是針對整個工程的。正確的應(yīng)該是在 一個CPP文件中定義如下:int ? g_Test;那么在使用的CPP文件中就應(yīng)該使用:extern ? int ? g_Test即可,如果還是使用int ? g_Test,那么就會產(chǎn)生LNK2005錯誤,一般錯誤錯誤信息類似:AAA.obj ? error ? LNK2005 ? int ? book ? c?book@@3HA ? already ? defined ? in ? BBB.obj。切記的就是不能給變量賦值否則還是會有LNK2005錯誤。 ?
? ? ? ? ? ? ? ? 這里需要的是“聲明”,不是“定義”!根據(jù)C++標(biāo)準(zhǔn)的規(guī)定,一個變量是聲明,必須同時滿足兩個條件,否則就是定義: ?
? (1)聲明必須使用extern關(guān)鍵字;(2)不能給變量賦初值 ?
? 所以,下面的是聲明: ?
? extern ? int ? a; ?
? 下面的是定義 ?
? int ? a; ? int ? a ? = ? 0; ? extern ? int ? a ? =0; ?
? B、對于那么編程不是那么嚴謹?shù)某绦騿T,總是在需要使用變量的文件中隨意定義一個全局變量,并且對于變量名也不予考慮,這也往往容易造成變量名重復(fù),而造成LNK2005錯誤。???


2.頭文件的包含重復(fù)。往往需要包含的頭文件中含有變量、函數(shù)、類的定義,在其它使用的地方又不得不多次包含之,如果頭文件中沒有相關(guān)的宏等防止重復(fù)鏈接 的措施,那么就會產(chǎn)生LNK2005錯誤。解決辦法是在需要包含的頭文件中做類似的處理:#ifndef ? MY_H_FILE ? ? ? //如果沒有定義這個宏 ?
? #define ? MY_H_FILE ? ? ? //定義這個宏 ?
? ……. ? ? ? //頭文件主體內(nèi)容 ?
? ……. ?
? #endif ?
? 上面是使用宏來做的,也可以使用預(yù)編譯來做,在頭文件中加入: ?
? #pragma ? once ?
? //頭文件主體???


3.使用第三方的庫造成的。這種情況主要是C運行期函數(shù)庫和MFC的庫沖突造成的。具體的辦法就是將那個提示出錯的庫放到另外一個庫的前面。另外選擇不同 的C函數(shù)庫,可能會引起這個錯誤。微軟和C有兩種C運行期函數(shù)庫,一種是普通的函數(shù)庫:LIBC.LIB,不支持多線程。另外一種是支持多線程的: msvcrt.lib。如果一個工程里,這兩種函數(shù)庫混合使用,可能會引起這個錯誤,一般情況下它需要MFC的庫先于C運行期函數(shù)庫被鏈接,因此建議使用 支持多線程的msvcrt.lib。所以在使用第三方的庫之前首先要知道它鏈接的是什么庫,否則就可能造成LNK2005錯誤。如果不得不使用第三方的 庫,可以嘗試按下面所說的方法修改,但不能保證一定能解決問題,前兩種方法是微軟提供的: ?
? A、選擇VC菜單Project->Settings->Link->Catagory選擇Input,再在Ignore ? libraries ? 的Edit欄中填入你需要忽略的庫,如:Nafxcwd.lib;Libcmtd.lib。然后在Object/library ? Modules的Edit欄中填入正確的庫的順序,這里需要你能確定什么是正確的順序,呵呵,God ? bless ? you! ?
? B、選擇VC菜單Project->Settings->Link頁,然后在Project ? Options的Edit欄中輸入/verbose:lib,這樣就可以在編譯鏈接程序過程中在輸出窗口看到鏈接的順序了。 ?
? C、選擇VC菜單Project->Settings->C/C++頁,Catagory選擇Code ? Generation后再在User ? Runtime ? libraray中選擇MultiThread ? DLL等其他庫,逐一嘗試。 ?
? 關(guān)于編譯器的相關(guān)處理過程,參考: ?
? http://www.donews.net/xzwenlan/archive/2004/12/23/211668.aspx ?
? ?
? 這就是我所遇到過的LNK2005錯誤的幾種情況,肯定還有其他的情況也可能造成這種錯誤,所以我不希望你在看完這篇文章以后,再遇到LNK2005錯誤 時候,不動腦筋的想對號入座的排除錯誤。編程的過程就是一個思考的過程,所以還是多多開動你的頭腦,那樣收獲會更多! ?
? ======================================= ?
? 支持,我在社區(qū)里也看到了許多LINK ? 2005錯 ?
? 補充一點,就是一次在用第三方庫時,由于errno被重定義,用多種方法都不能解決,后查找MSDN,發(fā)現(xiàn)link有個選項/FORCE可以解決,在IDE下 ?
? Project->Settings->Link頁,選categroy為custom,將force ? file ? output前打勾 ?
? 但會有警告 ?
? warning ? LNK4088: ? image ? being ? generated ? due ? to ? /FORCE ? option; ? image ? may ? not ? run ?
? 但的確解決了問題,這是由于VC對重定義比較嚴格,像BCB或GCC在庫中的重定義不會有任何警告或錯誤 ?
? ======================================== ?
? 我發(fā)現(xiàn)的另外一個出現(xiàn)LINK2005的現(xiàn)象,好像是由于名稱空間而引起的。我在dos下寫的程序沒有問題,但是放在mfc中就出現(xiàn)了這個鏈接錯誤。因為 起初圖省事,我在一個頭文件中寫了using ? namespace ? std,并且這個頭文件我多處使用,另外,我還使用了boost庫。后來,問題解決的方法非常奇怪,在一個頭文件中引用其他頭文件,這些頭文件的順序換一 下就通過了,那個出現(xiàn)問題的頭文件中我使用了std::map,當(dāng)我把這種容器使用模板代替后,鏈接就有沒事了。(例如:template< class ? coll>),后來感到模板技術(shù)還有這種效果,賺了!哈哈 ?
? ======================================== ?
? Knowledge ? Base ? ? ?
? What ? are ? the ? C ? and ? C++ ? libraries ? my ? program ? would ? link ? with? ?
? ?
? ------------------------------------------------------------------ ?
? | ? Compile ? ? ? Old ? ? ? ? ? ? ? ? New ? IOStream ? ? ? Libraries ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ?
? | ? Option ? ? ? ? IOStream ? ? ? or ? STL ? ? ? ? ? ? ? ? ? Linked ? With ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ?
? |================================================================| ?
? | ? /ML ? ? ? ? ? ? ? Yes ? ? ? ? ? ? ? ? No ? ? ? ? ? ? ? ? ? ? ? ? ? LIBC.LIB, ? ? ? ? LIBCI.LIB ? ? ? ? ? | ?
? | ? /MDd ? ? ? ? ? ? Yes ? ? ? ? ? ? ? ? No ? ? ? ? ? ? ? ? ? ? ? ? ? MSVCRTD.LIB, ? MSVCIRTD.LIB ? ? | ?
? ?
? 你的程序使用了/ML編譯選項,而程序依賴的.lib可能使用/MDd選項編譯,造成鏈接沖突. ?
? ?
? 統(tǒng)一編譯選項可回避此錯誤 ?
? Project ? Settings->C/C++ ? Tab->Category:CodeGeneration ?
? Use ? run-time ? library組合框中選擇Multithread ? Dll(或Debug ? Multithread ? Dll ? ) ?
? ?
? 注意:所有相關(guān)工程都應(yīng)該選擇相同編譯選項 ?
? ======================================== ?
? 微軟的MSDN中查到信息的 ?
? ?
? 可能的原因 ? ?
? ?
? 不慎同時與單線程庫和多線程庫鏈接。確保應(yīng)用程序項目文件只包括適當(dāng)?shù)膸欤⑶胰魏蔚谌綆煲堰m當(dāng)創(chuàng)建了單線程或多線程版本。 ? ?
? 該符號為封裝函數(shù)(通過用 ? /Gy ? 編譯創(chuàng)建),包含在多個文件中,但在各編譯間已改變。重新編譯所有包含 ? symbol ? 的文件。 ? ?
? 以不同的形式在不同庫中的兩個成員對象中定義了該符號,并且使用了這兩個成員對象。 ? ?
? 某個絕對符號被定義兩次,而每次定義的值不同。 ? ?
? 頭文件聲明并定義了變量。可能的解決方案有: ? ?
? 在 ? .h ? 中聲明變量:extern ? BOOL ? MyBool;,然后在 ? .c ? 或 ? .cpp ? 文件中向它分配:BOOL ? MyBool ? = ? FALSE;。 ? ?
? 將變量聲明為 ? Static。 ? ?
? 將變量聲明為 ? selectany。 ? ?
? 當(dāng)將 ? uuid.lib ? 與定義 ? GUID ? 的其他 ? .lib ? 文件(例如 ? oledb.lib ? 和 ? adsiid.lib)一起使用時。例如: ? ?
? oledb.lib(oledb_i.obj) ? : ? error ? LNK2005: ? _IID_ITransactionObject ?
? already ? defined ? in ? uuid.lib(go7.obj) ?
? 若要修復(fù),請將 ? /FORCE:MULTIPLE ? 添加到鏈接器命令行選項,并確保 ? uuid.lib ? 是引用的第一個庫。 ? ?
? ?
? 有關(guān)更多信息,請參閱知識庫文章: ? ?
? ?
? Q148652,PRB: ? LNK2005 ? Errors ? When ? Link ? C ? Run-Time ? Libraries ? Are ? Linked ? Before ? MFC ? Libraries。 ? ?
? Q140440,F(xiàn)IX: ? Global ? Overloaded ? Delete ? Operator ? Causes ? LNK2005。 ? ?
? Q184235,PRB: ? LNK2005 ? Errors ? on ? New ? and ? Delete ? When ? Defining ? _ATL_MIN_CRT。 ? ?
? 該錯誤之后為致命錯誤 ? LNK1169。 ?
? ======================================= ?
? 有時候因為工程使用了預(yù)編譯頭文件并且是增量編譯,所以當(dāng)你改動以后可能也會出現(xiàn)LNK2005錯誤,提示“XXXX已經(jīng)在XXXX.obj文件中定義” 的消息,這時候只要Rebuild ? All一般都能解決問題。這是因為頭文件的順序被改動等等操作造成的。 ?
? 最后要說明的:事物是在不斷變化中的,C++的標(biāo)準(zhǔn)在變化,編譯器也在變化,所以并不是所有的LNK2005錯誤都可以在這里找到答案,但是至少它能給你以提示。學(xué)習(xí)并思考才是正確的!????