Vs2005下重複定義的問題解決 ... already defined in ...

方案一、

編程中經常能遇到LNK2005錯誤——重複定義錯誤,其實LNK2005錯誤並不是一個很難解決的錯誤。弄清楚它形成的原因,就可以輕鬆解決它了。  
   
  造成LNK2005錯誤主要有以下幾種情況:  
  1.重複定義全局變量。可能存在兩種情況:  
 A、對於一些初學編程的程序員,有時候會以爲需要使用全局變量的地方就可以使用定義申明一下。其實這是錯誤的,全局變量是針對整個工程的。正確的應該是在一個CPP文件中定義如下:int   g_Test;那麼在使用的CPP文件中就應該使用:extern   int   g_Test即可,如果還是使用int   g_Test,那麼就會產生LNK2005錯誤,一般錯誤錯誤信息類似:AAA.obj   error   LNK2005   int   book   c?book@@3HA   already   defined   in   BBB.obj。切記的就是不能給變量賦值否則還是會有LNK2005錯誤。  
 這裏需要的是“聲明”,不是“定義”!根據C++標準的規定,一個變量是聲明,必須同時滿足兩個條件,否則就是定義:  
  (1)聲明必須使用extern關鍵字;(2)不能給變量賦初值  
 所以,下面的是聲明:  
  extern   int   a;  
  下面的是定義  
  int   a;   int   a   =   0;   extern   int   a   =0;  
 B、對於那麼編程不是那麼嚴謹的程序員,總是在需要使用變量的文件中隨意定義一個全局變量,並且對於變量名也不予考慮,這也往往容易造成變量名重複,而造成LNK2005錯誤。  
   
  2.頭文件的包含重複。往往需要包含的頭文件中含有變量、函數、類的定義,在其它使用的地方又不得不多次包含之,如果頭文件中沒有相關的宏等防止重複鏈接的措施,那麼就會產生LNK2005錯誤。解決辦法是在需要包含的頭文件中做類似的處理:#ifndef   MY_H_FILE       //如果沒有定義這個宏  
  #define   MY_H_FILE       //定義這個宏  
  …….       //頭文件主體內容  
  …….  
  #endif  
  上面是使用宏來做的,也可以使用預編譯來做,在頭文件中加入:  
  #pragma   once  
  //頭文件主體  
 3.使用第三方的庫造成的。這種情況主要是C運行期函數庫和MFC的庫衝突造成的。具體的辦法就是將那個提示出錯的庫放到另外一個庫的前面。另外選擇不同的C 函數庫,可能會引起這個錯誤。微軟和C有兩種C運行期函數庫,一種是普通的函數庫:LIBC.LIB,不支持多線程。另外一種是支持多線程的: msvcrt.lib。如果一個工程裏,這兩種函數庫混合使用,可能會引起這個錯誤,一般情況下它需要MFC的庫先於C運行期函數庫被鏈接,因此建議使用支持多線程的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等其他庫,逐一嘗試。  
  關於編譯器的相關處理過程,參考:  
  http://www.donews.net/xzwenlan/archive/2004/12/23/211668.aspx  
   
 這就是我所遇到過的LNK2005錯誤的幾種情況,肯定還有其他的情況也可能造成這種錯誤,所以我不希望你在看完這篇文章以後,再遇到LNK2005錯誤時候,不動腦筋的想對號入座的排除錯誤。編程的過程就是一個思考的過程,所以還是多多開動你的頭腦,那樣收穫會更多!   


方案二、
LNK2005...already defined...ERROR

鏈接時出錯提示:

LIBCMT.lib(crt0dat.obj) : error LNK2005: __amsg_exit already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(crt0dat.obj) : error LNK2005: __initterm_e already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(crt0dat.obj) : error LNK2005: _exit already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(crt0dat.obj) : error LNK2005: __exit already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(crt0dat.obj) : error LNK2005: __cexit already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(fflush.obj) : error LNK2005: _fflush already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(setlocal.obj) : error LNK2005: __configthreadlocale already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(tidtable.obj) : error LNK2005: __encode_pointer already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(tidtable.obj) : error LNK2005: __decode_pointer already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(invarg.obj) : error LNK2005: __invoke_watson already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(realloc.obj) : error LNK2005: _realloc already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(crt0init.obj) : error LNK2005: ___xi_a already defined in MSVCRTD.lib(cinitexe.obj)
LIBCMT.lib(crt0init.obj) : error LNK2005: ___xi_z already defined in MSVCRTD.lib(cinitexe.obj)
LIBCMT.lib(crt0init.obj) : error LNK2005: ___xc_a already defined in MSVCRTD.lib(cinitexe.obj)
LIBCMT.lib(crt0init.obj) : error LNK2005: ___xc_z already defined in MSVCRTD.lib(cinitexe.obj)
LIBCMT.lib(hooks.obj) : error LNK2005: "void __cdecl terminate(void)" (?terminate@@YAXXZ) already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(winxfltr.obj) : error LNK2005: __XcptFilter already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(mlock.obj) : error LNK2005: __unlock already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(mlock.obj) : error LNK2005: __lock already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(dosmap.obj) : error LNK2005: __errno already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(crt0.obj) : error LNK2005: _mainCRTStartup already defined in MSVCRTD.lib(crtexe.obj)
LIBCMT.lib(errmode.obj) : error LNK2005: ___set_app_type already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(isctype.obj) : error LNK2005: __isctype already defined in MSVCRTD.lib(MSVCR80D.dll)
LIBCMT.lib(tolower.obj) : error LNK2005: _tolower already defined in MSVCRTD.lib(MSVCR80D.dll)

解決方案:
Project Properties, Linker, Input, 右邊有個Ignore Specific Library,輸入"MSVCRTD.lib",確定即可。
posted on 2007-04-29 21:42 陳勳 閱讀(1365) 評論(0)  編輯 收藏 所屬分類: 解決方案-Visual Studio Linking

方案三、
發貼心情 error LNK2005: _DllMain@12 already defined in AUDIO.obj 處理方法
VC++6.0中編譯鏈接過程出錯:
mfcs42d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in AUDIO.obj


症狀
當 C 運行時 (CRT) 庫和 Microsoft 基礎類 (MFC) 庫的鏈接順序有誤時,可能會出現以下 LNK2005 錯誤之一:
nafxcwd.lib(afxmem.obj) :error LNK2005:
"void * __cdecl operator new(unsigned int)"(??2@YAPAXI@Z) already
defined in LIBCMTD.lib(new.obj) 
nafxcwd.lib(afxmem.obj) :error LNK2005:
"void __cdecl operator delete(void *)"(??3@YAXPAX@Z) already defined
in LIBCMTD.lib(dbgnew.obj) 
nafxcwd.lib(afxmem.obj) :error LNK2005:
"void * __cdecl operator new(unsigned int,int,char const *,int)"
(??2@YAPAXIHPBDH@Z) already defined in LIBCMTD.lib(dbgnew.obj) 
mfcs40d.lib(dllmodul.obj):error LNK2005:_DllMain@12 already defined in
MSVCRTD.LIB (dllmain.obj) 
mfcs42d.lib(dllmodul.obj):error LNK2005:_DllMain@12 already defined in
msvcrtd.lib(dllmain.obj) 


原因
CRT 庫對 new、delete 和 DllMain 函數使用弱外部鏈接。MFC 庫也包含 new、delete 和 DllMain 函數。這些函數要求先鏈接 MFC 庫,然後再鏈接 CRT 庫。 


解決方案一:強制鏈接器按照正確的順序鏈接庫
1. 在“項目”菜單上,單擊“設置”。 
2. 在“項目設置”對話框的“以下項目的設置”視圖中,單擊以選中出現鏈接錯誤的項目配置。 
3. 在“鏈接”選項卡上,單擊以選中“類別”組合框中的“輸入”。 
4. 在“忽略庫”框中,插入庫名(例如,Nafxcwd.lib;Libcmtd.lib)。

注意:等效的鏈接器命令行是:/NOD:<library name>。 
5. 在“對象/庫模塊”框中,插入庫名。必須確保這些庫按順序列出,而且是行中的前兩個庫(例如,Nafxcwd.lib 和 Libcmtd.lib)。 
要在 Visual C++ .NET 中設置該選項,請閱讀“設置 Visual C++ 項目屬性”聯機幫助主題。

解決方案二:找到並糾正出現問題的模塊
要查看當前的庫鏈接順序,請按照下列步驟操作: 1. 在“項目”菜單上,單擊“設置”。 
2. 在“項目設置”對話框的“以下項目的設置”視圖中,單擊以選中出現鏈接錯誤的項目配置。 
3. 在“鏈接”選項卡上的“項目選項”框中鍵入 /verbose:lib。 
4. 重新生成項目。在鏈接過程中,這些庫將在輸出窗口中列出。 


狀態
這種現象是設計導致的。


更多信息
使用 MFC 庫時,務必先鏈接它們,然後再鏈接 CRT 庫。這可以通過確保項目中的每個文件都首先包含 Msdev/Mfc/Include/ Afx.h 來完成。直接包含 (#include <Afx.h>) 或間接包含 (#include < Stdafx.h>) 都可以。Afx.h 包含文件會通過使用 #pragma comment (lib,"<libname> ") 指令來強制採用庫的正確順序。 

如果源文件的擴展名爲 .c,或者該文件的擴展名爲 .cpp 但不使用 MFC,則可以創建一個較小的頭文件 (Forcelib.h) 並將其放在模塊的頂端。這個新的頭文件可確保按照正確的順序搜索庫。

Visual C++ 不包含該頭文件。要創建此文件,請按照下列步驟操作: 1. 打開 Msdev/Mfc/Include/Afx.h。 
2. 選定 #ifndef _AFX_NOFORCE_LIBS 和 #endif //!_AFX_NOFORCE_LIBS 之間的行。 
3. 將選定部分複製到 Windows 剪貼板。 
4. 創建一個新文本文件。 
5. 將剪貼板的內容粘貼到這個新文件中。  
6. 將該文件另存爲 Msdev/Mfc/Include/Forcelib.h。 


在 Visual C++ .NET 中重現問題的步驟
1. 啓動 Microsoft Visual Studio .NET。 
2. 在“文件”菜單上,指向“新建”,然後單擊“項目”。 
3. 單擊“項目類型”下的“Visual C++ 項目”,然後單擊“模板”下的“MFC 應用程序”。 
4. 在“名稱”文本框中,鍵入 Q148652。 
5. 在“位置”文本框中,鍵入 C:/Test,然後單擊“確定”。 
6. 在“MFC 應用程序嚮導”對話框中,單擊“應用程序類型”。 
7. 單擊“應用程序類型”下的“基於對話框”,然後單擊“MFC 的使用”下的“在靜態庫中使用 MFC”。 
8. 單擊“完成”。 
9. 在“解決方案資源管理器”中,選擇“源文件”下的全部三個 .cpp 文件。 
10. 右鍵單擊三個選定的文件,然後單擊“刪除”。 
11. 右鍵單擊“源文件”,指向“添加”,然後單擊“添加新項”。 
12. 單擊“模板”下的“C++ 文件”。在“名稱”文本框中,鍵入 Aa。單擊“打開”。 
13. 將以下代碼粘貼到 Aa.cpp 中:int test(){new int; return 1;}
 
14. 右鍵單擊“源文件”,指向“添加”,然後單擊“添加現有項”。  
15. 選擇以下文件: &#8226; Q148652.cpp 
&#8226; Q148652Dlg.cpp 
&#8226; stdafx.cpp 
 
16. 單擊“打開”。 
17. 您在第 15 步中選擇的文件將出現在“源文件”下。 
18. 選擇“源文件”下的全部四個 .cpp 文件。 
19. 右鍵單擊選定的四個 .cpp 文件,然後單擊“屬性”。 
20. 展開“配置屬性”,然後展開“C/C++”。 
21. 單擊“預編譯頭”。 
22. 將“創建/使用預編譯頭”屬性設置爲“不使用預編譯頭”。單擊“確定”。 
23. 在“生成”菜單上,單擊“重新生成解決方案”。

本人Aladdin已採用的方案:
方案三中的解決方案一:強制鏈接器按照正確的順序鏈接庫
1. 在“項目”菜單上,單擊“設置”。 
2. 在“項目設置”對話框的“以下項目的設置”視圖中,單擊以選中出現鏈接錯誤的項目配置。 
3. 在“鏈接”選項卡上,單擊以選中“類別”組合框中的“輸入”。 
4. 在“忽略庫”框中,插入庫名(例如,Nafxcwd.lib;Libcmtd.lib)。 注意:等效的鏈接器命令行是:/NOD:<library name>。 
5. 在“對象/庫模塊”框中,插入庫名。必須確保這些庫按順序列出,而且是行中的前兩個庫(例如,Nafxcwd.lib 和 Libcmtd.lib)。

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