vs LNK2019 無法解析的外部符號 ***,該符號在函數 WinMain 中被引用


 

一般鏈接錯誤都是因為包含頭文件與lib庫不匹配(無導出函數、lib庫的release debug版本混亂、庫引用的優先級、編譯器設置mt/mtd等等)造成的。

 


錯誤    LNK2019    無法解析的外部符號 "int __cdecl pipe_server(void)" (?pipe_server@@YAHXZ),該符號在函數 WinMain 中被引用   

首先因為是c工程 引用了c++代碼,混編時會出現這種問題,因為我就一個小工程,就把c變成了cpp后綴。很多錯誤消失了,但是還是出現這種錯誤,原來是call的方式不對 應該以c的方式call

#ifdef __cplusplus
extern "C" {
#endif

	int pipe_server(VOID); 

#ifdef __cplusplus
}
#endif

 此時報錯:
錯誤    LNK2019    無法解析的外部符號 pipe_server,該符號在函數 WinMain 中被引用   
因為我沒有引用外部庫,所以排除lib庫的因素,但是這個錯誤確實是鏈接的問題,找到定義了卻找不到實現

想編譯.h對應的cpp文件看看,但是發現對應的,發現右鍵編譯是灰色的。問題找到了,原因是創建時只想創建一個.h頭文件,隨着需求增加就把一些實現放進去了,僅僅在該文件上重命名成了.cpp,vs並沒有隨着重命名更改文件的屬性。

右鍵該cpp文件,-屬性-常規 -項類型 “C/C++ 標頭” 一般的應該是“C/C++ 編譯器”,更改之后順利編譯通過。 vs2015原來還記錄這個,感覺像是vs的一個bug。

 

參考

----------------------------------------------------------------------------------------------------------------------------

http://www.cnblogs.com/hiloves/p/4678848.html

“error LNK2019: 無法解析的外部符號”之分析

最近在用VS 2008開發,初學遇到不少問題,最頭疼的問題之一就是:LNK2019。

百度一下講的並不夠全面,反正都沒解決我的問題。

error LNK2019問題在VC 6.0中是error LNK2001: unresolved external symbol問題,可能錯誤號改了。

編譯時出現類似這樣的錯誤:Dlgcode.obj : error LNK2019: 無法解析的外部符號 _readRegmark,該符號在函數 _AboutDlgProc@16 中被引用。這種錯誤的本質是鏈接器無法在已編譯的obj、lib或dll文件中找到函數定義。

1、這是百度找到的方法:http://jingyan.baidu.com/article/4d58d54135d7a79dd4e9c0ad.html。就是有頭文件(有了函數聲明)卻沒有lib。一般出現於你使用了第三方提供的庫,下載了頭文件卻忘了載庫文件,或庫文件忘記放到相應的目錄下了。

2、你自己寫的函數聲明的頭文件也寫了函數定義的cpp文件,卻依然出現LNK2019錯誤。可能原因:忘記將這兩個文件加入工程了。一般出現於用Visual Studio和記事本(或UltraEdit)混合開發過程,你用記事本include了相應的頭文件,卻忘了在Visual Studio的工程中加入它們了。也可能出現於在解決方案的開發過程,在解決方案下的某個工程中加入了它們卻忘了在其他工程中加入,我只接觸過VC 6和VS 2008,中間好多年沒用過新版本VS,到2008時突然發現怎么多了個“解決方案”,“解決方案”下面還可以放好多工程,於是經常在一個工程中寫了共享的源代碼,卻忘了在別的工程中加入它們。這個問題類似於第1個,不同的是這個庫是你自己提供的,但沒有把它交給VS 2008編譯出來。

3、你自己寫的函數聲明的頭文件也寫了函數定義的cpp文件也加入工程了而且你很確定函數體肯定是在這個庫文件中,卻依然出現LNK2019錯誤。可能原因:C語言和C++語言混編,因為C++支持函數重載所以C++編譯器生成的庫文件中的函數名會面目全非,例如C編譯器會生成 _readRegmark 這個函數名,而C++編譯器則生成了"void __cdecl readRegmark(char *)" (?readRegmark@@YAXPAD@Z)這么個函數名。當你的函數是用C語言寫的,VS編譯器會按C語言規則編譯,但鏈接器卻不知道還傻傻的用C++規則的函數名去找結果就找不到了,而你還百般肯定TM的不就在這個庫中嗎你個睜眼瞎。解決:在C語言的頭文件中加入

復制代碼
#ifdef __cplusplus
extern "C" { #endif void readRegmark(char *regmark); //這里寫函數聲明  #ifdef __cplusplus } #endif
復制代碼

給鏈接器提示這個函數是C語言的,別TM找錯了。

4、這是我百度來的,姑且也放進來。http://blog.csdn.net/jtop0/article/details/5779782。模板聲明和實現要放在同一文件夾中。

5、也是百度來的。http://www.programlife.net/error-lnk2019.html。內聯函數定義在頭文件中。

6、百度的。http://jingyan.baidu.com/article/d621e8da0d7c022864913f40.html。錯誤的工程類型造成的。

7、貌似還有不盡之處。http://www.douban.com/note/65638800/

--------------------------------------------------------------------------------------------------------------------------------------------------------------

https://jingyan.baidu.com/article/d621e8da0d7c022864913f40.html

  1. 編譯時出現如下錯誤:

    1>MSVCRTD.lib(crtexe.obj) : error LNK2019: 無法解析的外部符號 _main,該符號在函數 ___tmainCRTStartup 中被引用

  2. 右擊項目,打開“屬性”頁

     
  3. 更改上圖紅色框內容為/subsystem:windows。如果是剛開始默認的是/subsystem:windows

    則改為/subsytem:console

     
  4. 5

    再次編譯即過通過測試,運行結果截圖如下

 

----------------------------------------------------------------------------------------------------------------------------------------------------

https://www.douban.com/note/65638800/

學習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.不同版本的庫和編譯器的混合使用也能產生問題,因為新版的庫里可能包含早先的版本沒有的符號和說明。

  編程時打開了函數內聯(/Ob1或/Ob2),但是在描述該函數的相應頭文件里卻關閉了函數內聯(沒有inline關鍵字),這時將得到該錯誤信息。為避免該問題的發生,應該在相應的頭文件中用inline關鍵字標志內聯函數。

  8.不正確的/SUBSYSTEM或/ENTRY設置也能導致LNK2001。

解決方法:

解決外部符號錯誤:_main,_WinMain@16,__beginthreadex
在創建MFC項目時, 不使用MFC AppWizard向導, 就會在編譯時產生很多連接錯誤, 如error LNK2001錯誤, 典型的錯誤提示有:
libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@
msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
1. Windows子系統設置錯誤, 提示:
libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Windows項目要使用Windows子系統, 而不是Console, 可以這樣設置:

[Project] --> [Settings] --> 選擇"Link"屬性頁, 在Project Options中將/subsystem:console改成/subsystem:windows
2. Console子系統設置錯誤, 提示:
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@控制台項目要使用Console子系統, 而不是Windows, 設置:

[Project] --> [Settings] --> 選擇"Link"屬性頁

3. 程序入口設置錯誤, 提示:
msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@通常, MFC項目的程序入口函數是WinMain, 如果編譯項目的Unicode版本, 程序入口必須改為wWinMainCRTStartup, 所以需要重新設置程序入口:

[Project] --> [Settings] --> 選擇"Link"屬性頁, 在Category中選擇Output, 再在Entry-point symbol中填入wWinMainCRTStartup, 即可
4. 線程運行時庫設置錯誤, 提示:nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex這是因為MFC要使用多線程時庫, 需要更改設置:
[Project] --> [Settings] --> 選擇"C/C++"屬性頁, 在Category中選擇Code Generation,再在Use run-time library中選擇Debug Multithreaded或者multithreaded

其中, Single-Threaded 單線程靜態鏈接庫(release版本)
Multithreaded 多線程靜態鏈接庫(release版本)
multithreaded DLL 多線程動態鏈接庫(release版本)
Debug Single-Threaded 單線程靜態鏈接庫(debug版本)
Debug Multithreaded 多線程靜態鏈接庫(debug版本) )
Debug Multithreaded DLL 多線程動態鏈接庫(debug版本)
單線程: 不需要多線程調用時, 多用在DOS環境下
多線程: 可以並發運行
靜態庫: 直接將庫與程序Link, 可以脫離MFC庫運行
動態庫: 需要相應的DLL動態庫, 程序才能運行
release版本: 正式發布時使用
debug版本: 調試階段使用

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

http://www.roboby.com/%e6%80%aa%e5%bc%82%e7%9a%84-linker-error-lnk2019.html

怪異的 Linker Error LNK2019

今天碰到一個很奇怪的鏈接錯誤:LNK2019.

通常碰到這個問題,都是因為只有申明沒有實現導致的。要么是lib庫沒鏈接進來,要么是工程中只有頭文件,沒有添加其對應的cpp文件,導致只有申明沒有定義。

而今天碰到的奇葩問題是,同一個工程里,h文件及其對應的cpp文件都在工程中,而且通過h文件中的函數申明按F12鍵轉到定義也沒問題,即,申明和定義都沒問題。

最后猛然發現, 頭文件中對一個類型的預定義出問題了!本來此類型是個struct,結果預定義成了class!

這就很好理解了:由於一個類在頭文件中可能要用到另一個類型,又不想在頭文件中包含另一個類型的頭文件,或者因為循環引用的問題,沒法在這里包含另一個類的頭文件,則我們在這里先預定義這個類的申明,這樣,就可以在頭文件中用這個類來申明變量(只能申明指針變量,而不能使用實體,因為實體會真正導致使用另一個類的類定義),然后在cpp文件中才真正包含另一個類的頭文件,並為這個預先定義的指針變量new一個實體對象。

那么問題來了,如果在對另一個類做預定義時本來是class,卻定義成了struct,或者本來是struct,卻錯誤的定義成了class,那么對於頭文件,編譯的時候使用的是預定義符號,而cpp文件中由於包含了另一個類的頭文件,使用的是真正的申明和定義。

這種錯誤目前幾乎所有編譯器都會放過去的,但是鏈接的時候,目前看gcc編譯器是放過去了,但微軟的vc鏈接器包KNK2019鏈接錯誤!

這個問題,實在是因為黔驢技窮,耗費了好幾個小時后沒轍了,所以才打開錯誤警告才發現的。

 


免責聲明!

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



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