今天朋友在VS 2017里遇到一個LNK2019的錯誤,排查后發現是直接用VS打開了三個文件,但是通不過編譯:

把這三個文件添加到同一個項目文件里就可以通過編譯並正常運行了:

這樣就可以正常運行了。
正好在大四下做項目的時候也遇到過不少次2019錯誤,現在在網上搜集到一個整合了錯誤原因的文章,分享一下,也留個筆記
原文地址:CSDN:wanttifa 2020-08-28 10:26:00 鏈接器工具錯誤 LNK2019
文章目錄
- 可能的原因
-
- 1.不編譯包含符號定義的源文件
- 2.未鏈接包含符號定義的對象文件或庫
- 3.符號聲明的拼寫與符號的定義不同
- 4.使用了函數,但是參數的類型或數量與函數定義不匹配
- 5.已聲明但未定義函數或變量
- 6.函數聲明和函數定義之間的調用約定不同
- 7.符號在 C 文件中定義,但未 :::no-loc(extern)::: 在 c + + 文件中使用 "C" 進行聲明
- 7.符號定義為 :::no-loc(static)::: ,稍后在文件外部引用
- 8. :::no-loc(static):::未定義類的成員
- 9.生成依賴項僅在解決方案中定義為項目依賴項
- 10.未定義入口點
- 11.使用 Windows 應用程序的設置生成控制台應用程序
- 12.嘗試將64位庫鏈接到32位代碼,或將32位庫鏈接到64代碼
- 13.將不同的編譯器選項用於不同源文件中的函數內聯
- 14.在其作用域外使用自動變量
- 15.調用內部函數或將參數類型傳遞到目標體系結構不支持的內部函數
- 16.混合使用本機代碼 :::no-loc(wchar_t)::: 和代碼
- 第三方庫問題和 vcpkg
- 診斷工具
- 示例
- 其他資源
已編譯的函數的函數對符號進行引用或調用,但是鏈接器在要鏈接的任何庫或對象文件中都找不到符號定義。
此錯誤消息后跟嚴重錯誤LNK1120。 若要修復錯誤 LNK1120,必須先修復所有 LNK2001 和 LNK2019 錯誤。
可能的原因
有多種方法可獲取此錯誤。 所有這些都涉及到鏈接器無法解析的函數或變量的引用,或查找的定義。 編譯器可以確定符號未聲明的時間,但無法判斷符號未定義的時間。 這是因為定義可能位於不同的源文件或庫中。 如果某個符號被引用但從未定義,則鏈接器將生成一個無法解析的 :::no-loc(extern)::: al 符號錯誤。
以下是一些導致 LNK2019 的常見問題:
1.不編譯包含符號定義的源文件
在 Visual Studio 中,請確保定義符號的源文件編譯為項目的一部分。 查看中間生成輸出目錄中是否有匹配的 .obj 文件。 如果未編譯源文件,請在解決方案資源管理器中右鍵單擊該文件,然后選擇 “屬性” 以檢查該文件的屬性。 “配置屬性” " > 常規" 頁應顯示C/c + + 編譯器的項類型。 在命令行上,確保編譯了包含定義的源文件。
2.未鏈接包含符號定義的對象文件或庫
在 Visual Studio 中,請確保包含符號定義的對象文件或庫鏈接為項目的一部分。 在命令行上,確保要鏈接的文件列表包含對象文件或庫。
3.符號聲明的拼寫與符號的定義不同
驗證在聲明和定義中以及使用或調用該符號的任何位置都使用正確的拼寫和大小寫。
4.使用了函數,但是參數的類型或數量與函數定義不匹配
函數聲明必須匹配定義。 請確保函數調用與聲明匹配,並且聲明與定義匹配。 調用模板函數的代碼還必須擁有包括與定義相同的模板參數的匹配模板函數聲明。 有關模板聲明不匹配的示例,請參閱示例部分中的示例 LNK2019e。
5.已聲明但未定義函數或變量
當標頭文件中存在聲明,但未實現匹配定義時,可能會出現 LNK2019。 對於成員函數或 :::no-loc(static)::: 數據成員,實現必須包括類范圍選擇器。 有關示例,請參見 Missing Function Body or Variable。
6.函數聲明和函數定義之間的調用約定不同
調用約定( :::no-loc(__cdecl)::: 、 :::no-loc(__stdcall)::: 、 :::no-loc(__fastcall)::: 或 :::no-loc(__vectorcall)::: )作為修飾名稱的一部分進行編碼。 請確保調用約定是相同的。
7.符號在 C 文件中定義,但未 :::no-loc(extern)::: 在 c + + 文件中使用 “C” 進行聲明
在編譯為 c 的文件中定義的符號具有與 c + + 文件中聲明的符號不同的修飾名稱,除非使用 :::no-loc(extern)::: "C"修飾符。 請確保該聲明匹配每個符號的編譯鏈接。 同樣,如果在 C 程序將使用的 C++ 文件中定義符號,請在定義中使用 :::no-loc(extern)::: “C” 。
7.符號定義為 :::no-loc(static)::: ,稍后在文件外部引用
在 c + + 中,與 C 不同, global :::no-loc(const)::: 螞蟻有 :::no-loc(static)::: 鏈接。 若要繞過此限制,可以 :::no-loc(const)::: 在標頭文件中包括初始化並將該標頭包含在 .cpp 文件中,也可以將變量設置為非 :::no-loc(const)::: ant,並使用 :::no-loc(const)::: ant 引用來訪問它。
8. :::no-loc(static):::未定義類的成員
:::no-loc(static):::類成員必須具有唯一的定義,否則它將違反單個定義規則。 :::no-loc(static):::無法以內聯方式定義的類成員必須通過使用其完全限定名稱在一個源文件中進行定義。 如果根本沒有定義此方法,則鏈接器會生成 LNK2019。
9.生成依賴項僅在解決方案中定義為項目依賴項
在 Visual Studio 的早期版本中,此級別的依賴項已經足夠。 但是,從 Visual Studio 2010 開始,Visual Studio 需要一個項目到項目的引用。 如果你的項目沒有項目到項目的引用,則可能會收到此鏈接器錯誤。 添加項目到項目引用以修復此錯誤。
10.未定義入口點
應用程序代碼必須 :::no-loc(main)::: :::no-loc(wmain)::: 為控制台應用程序和 :::no-loc(WinMain)::: 或 :::no-loc(wWinMain)::: Windows 應用程序定義適當的入口點。 有關詳細信息,請參閱 :::no-loc(main)::: 函數和命令行參數或 :::no-loc(WinMain)::: 函數。 若要使用自定義入口點,請指定/ENTRY (入口點符號)鏈接器選項。
11.使用 Windows 應用程序的設置生成控制台應用程序
如果錯誤消息類似於函數function_name ** :::no-loc(extern)::: :::no-loc(WinMain)::: 中引用的無法解析的 al 符號**,則使用 /SUBSYSTEM:控制台(而不是 /SUBSYSTEM: WINDOWS)進行鏈接。 有關此設置的詳細信息以及如何在 Visual Studio 中設置此屬性的說明,請參閱 /SUBSYSTEM (Specify Subsystem)。
12.嘗試將64位庫鏈接到32位代碼,或將32位庫鏈接到64代碼
鏈接到代碼的庫和對象文件必須編譯為與代碼相同的體系結構。 確保項目引用的庫是針對與項目相同的體系結構編譯的。 請確保 " /LIBPATH " 或 “其他庫目錄” 屬性指向為正確的體系結構生成的庫。
13.將不同的編譯器選項用於不同源文件中的函數內聯
使用 .cpp 文件中定義的內聯函數並在不同源文件中混合使用函數內聯編譯器可能會導致 LNK2019。 有關詳細信息,請參閱 Function Inlining Problems。
14.在其作用域外使用自動變量
自動(函數范圍)變量僅可在該函數的范圍內使用。 不能 :::no-loc(extern)::: 在其他源文件中聲明和使用這些變量。 有關示例,請參見 Automatic (Function Scope) Variables。
15.調用內部函數或將參數類型傳遞到目標體系結構不支持的內部函數
例如,如果您使用 :::no-loc(AVX2)::: 內部函數,但未指定 / :::no-loc(ARCH)::: : :::no-loc(AVX2)::: 編譯器選項,則編譯器會假定該內部 :::no-loc(extern)::: 函數為 al 函數。 編譯器不會生成內聯指令,而是生成對 :::no-loc(extern)::: 與內部函數同名的 al 符號的調用。 當鏈接器嘗試找到此缺失函數的定義時,它會生成 LNK2019。 請確保僅使用目標體系結構支持的內部函數和類型。
16.混合使用本機代碼 :::no-loc(wchar_t)::: 和代碼
默認情況下,在 Visual Studio 2005 中完成的 c + + 語言一致性工作 :::no-loc(wchar_t)::: 是本機類型。 如果並非所有文件都是使用相同的 **/zc: :::no-loc(wchar_t)::: **設置編譯的,則類型引用可能不會解析為兼容的類型。 請確保 :::no-loc(wchar_t)::: 所有庫和對象文件中的類型都是兼容的。 請從 typedef 中更新 :::no-loc(wchar_t)::: ,或在編譯時使用一致的 **/zc: :::no-loc(wchar_t)::: **設置。
第三方庫問題和 vcpkg
如果嘗試在生成過程中配置第三方庫時遇到此錯誤,請考慮使用vcpkg(c + + 程序包管理器)安裝和生成庫。 vcpkg 支持較大和不斷增長的第三方庫列表。 它將成功生成所需的所有配置屬性和依賴項設置為項目的一部分。
診斷工具
有時很難判斷鏈接器無法找到特定的符號定義的原因。 通常,問題是您在生成中未包含包含定義的代碼。 或者,生成選項已為 al 符號創建了不同的修飾名稱 :::no-loc(extern)::: 。 有多種工具和選項可以幫助你診斷 LNK2019 錯誤。
- /:::no-loc(VERBOSE):::鏈接器選項可幫助你確定鏈接器引用了哪些文件。 此選項可幫助您驗證您的生成中是否包括包含符號定義的文件。
- /:::no-loc(EXPORTS):::實用工具的和 /:::no-loc(SYMBOLS)::: 選項 :::no-loc(DUMPBIN)::: 可幫助你發現 .dll 和對象或庫文件中定義了哪些符號。 請確保導出的修飾名與鏈接器搜索的修飾名稱匹配。
- :::no-loc(UNDNAME)::: 實用工具可以顯示修飾名稱的等效未修飾 :::no-loc(extern)::: al 符號。
示例
以下是一些導致 LNK2019 錯誤的代碼示例,以及關於如何修復錯誤的信息。
1.聲明了符號,但是未對其進行定義
在此示例中, :::no-loc(extern)::: 聲明了 al 變量但未對其進行定義:
// LNK2019.cpp
// Compile by using: cl /EHsc /W4 LNK2019.cpp
// LNK2019 expected
:::no-loc(extern)::: char B[100]; // B isn't available to the linker
int :::no-loc(main):::() {
B[0] = ' '; // LNK2019
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
下面是另一個示例,其中變量和函數聲明為 :::no-loc(extern)::: 但未提供定義:
// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
:::no-loc(extern)::: int i;
:::no-loc(extern)::: void g();
void f() {
i++;
g();
}
int :::no-loc(main):::() {}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
除非 i 和 g 是在生成中包含的其中一個文件中定義的,否則鏈接器會生成 LNK2019。 你可以通過將包含定義的源代碼文件作為編譯的一部分包括在其中來修復錯誤。 或者,可以將包含定義的 .obj 文件或 .lib 文件傳遞到鏈接器。
2.:::no-loc(static):::已聲明但未定義數據成員
當 :::no-loc(static)::: 聲明但未定義數據成員時,也可能出現 LNK2019。 以下示例生成 LNK2019,並演示如何修復此錯誤。
// LNK2019b.cpp
// Compile by using: cl /EHsc LNK2019b.cpp
// LNK2019 expected
struct C {
:::no-loc(static)::: int s;
};
// Uncomment the following line to fix the error.
// int C:😒;
int :::no-loc(main):::() {
C c;
C::s = 1;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3.聲明參數不匹配定義
調用模板函數的代碼必須擁有匹配的模板函數聲明。 聲明必須包括與定義相同的模板參數。 以下示例在用戶定義的運算符上生成 LNK2019,並演示如何修復此錯誤。
// LNK2019e.cpp
// compile by using: cl /EHsc LNK2019e.cpp
// LNK2019 expected
#include <iostream>
using namespace std;
template<class T> class
Test {
// The operator<< declaration doesn't match the definition below:
friend ostream& operator<<(ostream&, Test&);
// To fix, replace the line above with the following:
// template<typename T> friend ostream& operator<<(ostream&, Test<T>&);
};
template<typename T>
ostream& operator<<(ostream& os, Test<T>& tt) {
return os;
}
int :::no-loc(main):::() {
Test<int> t;
cout << "Test: " << t << endl; // LNK2019 unresolved :::no-loc(extern):::al
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
4.:::no-loc(wchar_t):::類型定義不一致
此示例創建一個 DLL,該 DLL 包含一個使用的導出 WCHAR ,該導出將解析為 :::no-loc(wchar_t)::: 。
// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to :::no-loc(wchar_t):::
__declspec(dllexport) void func(WCHAR*) {}
- 1
- 2
- 3
- 4
- 5
下一個示例使用上一示例中的 DLL,並生成 LNK2019,因為類型 unsigned short* 和 WCHAR* 不同。
// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);
int :::no-loc(main):::() {
func(0);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
若要修復此錯誤,請將更改 unsigned short 為 :::no-loc(wchar_t)::: 或 WCHAR ,或使用/zc 編譯 LNK2019g **: :::no-loc(wchar_t)::: - **。
其他資源
有關 LNK2001 的可能原因和解決方案的詳細信息,請參閱 Stack Overflow 問題:未定義的引用/未解析的 " :::no-loc(extern)::: 符號錯誤",以及如何修復該錯誤?。
