原帖地址:http://hym131690.blog.163.com/blog/static/642553162009212104926450/
最近打算學習一下網路編程,而大部分socket編程環境都是Unix的,很是不便,在windows中總是不能編譯,特尋得一篇文章解決此癢。爽哉、爽哉!
linking... server.obj : error lnk2001: unresolved external symbol __imp__send@16
server.obj : error lnk2001: unresolved external symbol __imp__wsagetlasterror@0 s
erver.obj : error lnk2001: unresolved external symbol __imp__recv@16
server.obj : error lnk2001: unresolved external symbol __imp__wsacleanup@0
server.obj : error lnk2001: unresolved external symbol __imp__closesocket@4
server.obj : error lnk2001: unresolved external symbol __imp__inet_ntoa@4 s
erver.obj : error lnk2001: unresolved external symbol __imp__ntohs@4
server.obj : error lnk2001: unresolved external symbol __imp__accept@12
server.obj : error lnk2001: unresolved external symbol __imp__listen@8
server.obj : error lnk2001: unresolved external symbol __imp__bind@12
server.obj : error lnk2001: unresolved external symbol __imp__htons@4
server.obj : error lnk2001: unresolved external symbol __imp__htonl@4
server.obj : error lnk2001: unresolved external symbol __imp__inet_addr@4
server.obj : error lnk2001: unresolved external symbol __imp__socket@12
server.obj : error lnk2001: unresolved external symbol __imp__wsastartup@8
原因和解決辦法:
找不到相應函數,問題是Link選項裡沒有加入相應的lib庫,winsock要串連wsock32.lib。特定庫的找到辦法是看LNK2001中找不到的函數名,通過msdn或者其他手段擷取這個函數所在的庫名,連結進去就OK了。
可以在project->setting->Link->object/library modules 裡添加wsock32.lib, 也可在stdafx.cpp裡添加 #pragma comment(lib,"wsock32.lib")
一般來說, 這是工程的類型選擇錯誤引起的.如在VC中, 1.本來應該選擇"Win32 Console Application",而錯誤選擇了"Win32 Application" 2.使用了MFC的類,而選擇"工程"的"設定"不使用MFC庫編譯. 改正的方法有: 1. 選擇"工程"-> "設定"-> 串連,在底部的編輯視窗中,找到"/subsystem",把其改成 "/subsystem:console" "/subsystem:windows". 2.在"工程"-> "設定"->"一般"選項中,在MFC項中改為"USE MFC AS A SHARED DLL".
用VC++時經常會遇到連結錯誤LNK2001,該錯誤非常討厭,因為對於 編程者來說,最好改的錯誤莫過於編譯錯誤,而一般說來發生串連錯誤時, 編譯都已通過。產生串連錯誤的原因非常多,尤其LNK2001錯誤,常常使人不明其所以然。如果不深入地學習和理解VC++,要想改正串連錯誤LNK2001非 常困難。 初學者在學習VC++的過程中,遇到的LNK2001錯誤的錯誤訊息主要為: unresolved external symbol “symbol”(不確定的外部“符號”)。 如果串連程式不能在所有的庫和目標檔案內找到所引用的函數、變數或標籤,將產生此錯誤訊息。一般來說,發生錯誤的原因有兩個:一是所引用 的函數、變數不存在、拼字不正確或者使用錯誤;其次可能使用了不同版本 的串連庫。 以下是可能產生LNK2001錯誤的原因: 一.由於編碼錯誤導致的LNK2001。 1.不相匹配的程式碼或模組定義(.DEF)檔案能導致LNK2001。例如, 如果在C++ 源檔案內聲明了一變數“var1”,卻試圖在另一檔案內以變數 “VAR1”訪問該變數,將發生該錯誤。 2.如果使用的內嵌函式是在.CPP檔案內定義的,而不是在標頭檔內定 義將導致LNK2001錯誤。 3.調用函數時如果所用的參數類型同函式宣告時的類型不符將會產生 LNK2001。 4.試圖從基類的建構函式或解構函式中調用虛擬函數時將會導致LNK2001。 5.要注意函數和變數的可公用性,只有全域變數、函數是可公用的。 靜態函數和靜態變數具有相同的使用範圍限制。當試圖從檔案外部存取 任何沒有在該檔案內聲明的靜態變數時將導致編譯錯誤或LNK2001。 函數內聲明的變數(局部變數) 只能在該函數的範圍內使用。 C++ 的全域常量只有靜態串連效能。這不同於C,如果試圖在C++的 多個檔案內使用全域變數也會產生LNK2001錯誤。一種解決的方法是需要時在 標頭檔中加入該常量的初始化代碼,並在.CPP檔案中包含該標頭檔;另一種 方法是使用時給該變數賦以常數。 二.由於編譯和連結的設定而造成的LNK2001 1.如果編譯時間使用的是/NOD(/NODEFAULTLIB)選項,程式所需要的運行 庫和MFC庫在串連時由編譯器寫入目標檔案模組, 但除非在檔案中明確包含 這些庫名,否則這些庫不會被連結進工程檔案。在這種情況下使用/NOD將導 致錯誤LNK2001。 2.如果沒有為wWinMainCRTStartup設定程式入口,在使用Unicode和MFC 時將得到“unresolved external on _WinMain@16”的LNK2001錯誤資訊。 3.使用/MD選項編譯時間,既然所有的運行庫都被保留在動態連結程式庫之內, 源檔案中對“func”的引用,在目標檔案裡即對“__imp__func” 的引用。 如果試圖使用靜態庫LIBC.LIB或LIBCMT.LIB進行串連,將在__imp__func上發 生LNK2001;如果不使用/MD選項編譯,在使用MSVCxx.LIB串連時也會發生LNK2001。 4.使用/ML選項編譯時間,如用LIBCMT.LIB連結會在_errno上發生LNK2001。 5.當編譯調試版的應用程式時,如果採用發行版模態庫進行串連也會產 生LNK2001;同樣,使用調試版模態庫串連發行版應用程式時也會產生相同的 問題。 6.不同版本的庫和編譯器的混合使用也能產生問題,因為新版的庫裡可 能包含早先的版本沒有的符號和說明。 7.在不同的模組使用內聯和非內聯的編譯選項能夠導致LNK2001。如果 建立C++庫時開啟了函數內聯(/Ob1或/Ob2),但是在描述該函數的相應頭 檔案裡卻關閉了函數內聯(沒有inline關鍵字),這時將得到該錯誤資訊。 為避免該問題的發生,應該在相應的標頭檔中用inline關鍵字標誌內嵌函式。 8.不正確的/SUBSYSTEM或/ENTRY設定也能導致LNK2001。 其實,產生LNK2001的原因還有很多,以上的原因只是一部分而已,對初 學者來說這些就夠理解一陣子了。但是,分析錯誤原因的目的是為了避免錯 誤的發生。LNK2001錯誤雖然比較困難,但是只要注意到了上述問題,還是能 夠避免和予以解決的。
1、fatal error C1010: unexpected end of file while looking for precompiled header directive。
尋找先行編譯標頭檔路徑時遇到了不該遇到的檔案尾。(一般是沒有#include "stdafx.h")
2、fatal error C1083: Cannot open include file: 'R…….h': No such file or directory
不能開啟包含檔案“R…….h”:沒有這樣的檔案或目錄。
3、error C2011: 'C……': 'class' type redefinition
類“C……”重定義。
4、error C2018: unknown character '0xa3'
不認識的字元'0xa3'。(一般是漢字或中文標點符號)
5、error C2057: expected constant expression
希望是常量運算式。(一般出現在switch語句的case分支中)
6、error C2065: 'IDD_MYDIALOG' : undeclared identifier
“IDD_MYDIALOG”:未聲明過的標識符。
7、error C2082: redefinition of formal parameter 'bReset'
函數參數“bReset”在函數體中重定義。
8、error C2143: syntax error: missing ':' before '{'
句法錯誤:“{”前缺少“;”。
9、error C2146: syntax error : missing ';' before identifier 'dc'
句法錯誤:在“dc”前丟了“;”。
10、error C2196: case value '69' already used
值69已經用過。(一般出現在switch語句的case分支中)
編程中經常能遇到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",確定即可。
方案三、 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. 選擇以下檔案: • Q148652.cpp • Q148652Dlg.cpp • 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)。