連結器工具錯誤 LNK2019
函式 『function』 中所參考的未解析 external 符號 'symbol'
函式的編譯程式代碼會參考或呼叫符號,但連結器找不到任何連結庫或對象檔中的符號定義。
此錯誤訊息後面接著嚴重錯誤 LNK1120。 若要修正錯誤LNK1120,您必須先修正所有LNK2001和LNK2019錯誤。
可能的原因
有許多方法可取得此錯誤。 它們全都牽涉到連結器無法 解析的函式或變數參考,或尋找其定義。 編譯程式可以識別未 宣告符號的時機,但無法判斷未 定義符號的時機。 這是因為定義可能位於不同的原始程式檔或連結庫中。 如果參考符號但從未定義,鏈接器會產生未解析 extern的符號錯誤。
以下是一些造成 LNK2019 的常見問題:
未編譯包含符號定義的來源檔案
在 Visual Studio 中,確定定義符號的來源檔案會編譯為專案的一部分。 檢查中繼組建輸出目錄,以取得相符的 .obj 檔案。 如果未編譯來源檔案,請以滑鼠右鍵按兩下 方案總管 中的檔案,然後選擇 [屬性] 以檢查檔案的屬性。 [組態屬性一般]>頁面應該會顯示 C/C++ 編譯程式的項目類型。 在命令行上,確定已編譯包含定義的來源檔案。
包含符號定義的物件檔案或連結庫未連結
在 Visual Studio 中,確定包含符號定義的物件檔或連結庫已連結為專案的一部分。 在命令行上,確定要連結的檔案清單包含對象檔或連結庫。
符號的宣告與符號的定義不相同
請確認您在宣告和定義中使用正確的拼字和大寫,以及使用或呼叫符號的位置。
使用函式,但參數的類型或數目不符合函式定義
函式宣告必須與定義相符。 請確定函式呼叫符合宣告,而且宣告符合定義。 叫用函式範本的程式代碼也必須有相符的函式範本宣告,其中包含與定義相同的範本參數。 如需範本宣告不相符的範例,請參閱範例一節中的範例 LNK2019e.cpp。
已宣告函式或變數,但未定義
當宣告存在於頭檔中,但未實作相符的定義時,可能會發生LNK2019。 針對成員函式或 static 數據成員,實作必須包含類別範圍選取器。 如需範例,請參閱 Missing Function Body or Variable。
呼叫慣例在函式宣告和函式定義之間是不同的
某些呼叫慣例 (__cdecl
、 __stdcall
、 __fastcall
和 __vectorcall
) 會編碼為裝飾名稱的一部分。 請確定呼叫慣例相同。
符號定義在 C 檔案中,但宣告而不在 extern "C"
C++ 檔案中使用
編譯為 C 的檔案會針對與 C++ 檔案中宣告之相同符號的裝飾名稱建立裝飾名稱,除非您使用 extern "C"
修飾詞。 請確定宣告符合每個符號的編譯連結。 同樣地,如果您在 C++ 檔案中定義將由 C 程式使用的符號,請在定義中使用 extern "C"
。
符號定義為 static ,稍後在檔案外部參考
在 C++ 中,與 C 不同的是, 全域 const螞蟻 有 static
連結。 若要解決此問題,您可以在頭檔中包含 const
初始化,並在 .cpp 檔案中包含該標頭,或者您可以讓變數非const ant,並使用 constant 參考來存取它。
static未定義類別的成員
類別 static 成員必須具有唯一的定義,否則會違反單一定義規則。 static無法內嵌定義的類別成員必須使用其完整名稱,在一個原始程式檔中定義。 如果完全未定義,鏈接器會產生LNK2019。
組建相依性只會定義為方案中的專案相依性
在舊版的Visual Studio中,此層級的相依性就已足夠。 不過,從Visual Studio 2010開始,Visual Studio需要 專案對項目參考。 如果您的項目沒有項目對項目參考,您可能會收到此連結器錯誤。 加入專案對專案間的參考來修正此問題。
未定義進入點
應用程式程式代碼必須定義適當的進入點:main
或wmain
控制台應用程式,或WinMain
wWinMain
適用於 Windows 應用程式。 如需詳細資訊,請參閱函式和命令行自變數或WinMain
函式。main
若要使用自定義進入點,請指定 /ENTRY
[進入點符號] 連結器選項。
您可以使用 Windows 應用程式設定來建置主控台應用程式
如果錯誤訊息類似於函式function_name中所參考的未解析 external 符號WinMain,請使用 /SUBSYSTEM:CONSOLE
連結,/SUBSYSTEM:WINDOWS
而不是 。 如需此設定的詳細資訊,以及有關如何在Visual Studio中設定此屬性的指示,請參閱/SUBSYSTEM
(指定子系統)。
您嘗試將64位連結庫連結至32位程式代碼,或將32位連結庫連結至64位程序代碼
連結至程式代碼的連結庫和物件檔案必須針對與程式代碼相同的架構進行編譯。 請確定您的專案參考連結庫已針對與專案相同的架構進行編譯。 請確定 /LIBPATH
或 [其他連結庫目錄 ] 屬性指向為正確架構建置的連結庫。
您可以使用不同的編譯程式選項在不同的原始程式檔中內嵌函式
若使用在 .cpp 檔案中定義的內嵌函式,且又在不同的原始程式檔中混用函式內嵌編譯器選項,則可能會導致 LNK2019。 如需詳細資訊,請參閱 Function Inlining Problems。
您可以在其範圍之外使用自動變數
自動 (函式範圍) 變數只能在該函式的範圍內使用。 不能將這些變數宣告為 extern
,也不能在其他原始程式檔中加以使用。 如需範例,請參閱 Automatic (Function Scope) Variables。
您可以呼叫內部函數,或將自變數類型傳遞至目標架構上不支援的內建函式
例如,如果您使用 AVX2 內部函數,但未指定 /ARCH:AVX2
編譯程式選項,編譯程式會假設內部函數是 external函式。 編譯程式不會產生內嵌指令,而是產生與內建相同名稱的al符號呼叫 extern。 當連結器嘗試找出此遺漏函式的定義時,就會產生 LNK2019。 請確定您只使用目標架構支援的內建和類型。
您可以混合使用原生 wchar_t
程式代碼的程式碼與不使用的程式碼
在 Visual Studio 2005 中完成的 C++ 語言一致性工作預設為 wchar_t
原生類型。 如果並非所有檔案都已使用相同的 /Zc:wchar_t
設定編譯,類型參考可能無法解析為相容的類型。 請確定 wchar_t
所有連結庫和物件檔中的類型都相容。 從 wchar_t
typedef 更新,或在編譯時使用一致的 /Zc:wchar_t 設定。
當您連結舊版static連結庫時,您會收到 和 *scanf*
函式的錯誤*printf*
static在 Visual Studio 2015 之前,使用 Visual Studio 2015 版本所建置的連結庫,可能會在與 UCRT 連結時造成LNK2019錯誤。 UCRT 頭檔 <stdio.h>
、 <conio.h>
和 <wchar.h>
現在會將許多 *printf*
和 *scanf*
變化定義為 inline
函式。 內嵌函式是由一組較小的通用函式所實作。 標準 UCRT 連結庫不提供內嵌函式的個別匯出,其只會匯出通用函式。 有幾種方式可以解決此問題。 我們建議的方法是使用您目前的 Visual Studio 版本重建舊版連結庫。 請確定連結庫程式代碼會針對造成錯誤的 和 *scanf*
函式定義*printf*
使用標準標頭。 您無法重建的舊版連結庫的另一個選項是將 新增 legacy_stdio_definitions.lib
至您連結的連結庫清單。 此連結庫檔案提供 *printf*
內嵌在UCRT標頭中的和 *scanf*
函式符號。 如需詳細資訊,請參閱潛在升級問題概觀中的連結庫一節。
第三方連結庫問題和 vcpkg
如果您在嘗試將第三方連結庫設定為組建的一部分時看到此錯誤,請考慮使用 vcpkg。 vcpkg 是 C++ 套件管理員,會使用您現有的 Visual Studio 工具來安裝和建置連結庫。 vcpkg 支援大量且成長 的第三方連結庫清單。 它會設定成功建置所需的所有組態屬性和相依性,作為專案的一部分。
診斷工具
有時候很難分辨為什麼連結器找不到特定的符號定義。 問題通常是您尚未在組建中包含定義的程序代碼。 或者,建置選項已為 external符號建立不同的裝飾名稱。 有數個工具和選項可協助您診斷LNK2019錯誤。
連結
/VERBOSE
器選項可協助您判斷連結器參考的檔案。 這個選項可協助您確認包含符號定義的檔案是否包含在組建中。公用
/EXPORTS
程式的 和/SYMBOLS
選項 DUMPBIN 可協助您探索 .dll 和對象或連結庫檔案中定義的符號。 請確定匯出的裝飾名稱符合連結器搜尋的裝飾名稱。公用 UNDNAME 程式可以為您顯示裝飾名稱的對等未 extern取消編碼 al 符號。
範例
以下是造成LNK2019錯誤的數個程式代碼範例,以及如何修正錯誤的相關信息。
符號已宣告但未定義
在此範例中, extern會宣告al變數,但未定義:
// LNK2019.cpp
// Compile by using: cl /EHsc /W4 LNK2019.cpp
// LNK2019 expected
extern char B[100]; // B isn't available to the linker
int main() {
B[0] = ' '; // LNK2019
}
以下是另一個範例,其中會宣告變數和函式, extern
但未提供任何定義:
// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
i++;
g();
}
int main() {}
除非 i
和 g
定義在組建中包含的其中一個檔案中,否則鏈接器會產生LNK2019。 您可以包含原始碼檔案來修正此問題,其中包含此定義做為編譯的一部分。 或者,您可以將包含定義的檔案或.lib
檔案傳遞.obj
至連結器。
數據 static 成員已宣告但未定義
當宣告數據成員但未定義數據成員時 static ,也可能會發生LNK2019。 下列範例會產生 LNK2019,並示範如何修正此問題。
// LNK2019b.cpp
// Compile by using: cl /EHsc LNK2019b.cpp
// LNK2019 expected
struct C {
static int s;
};
// Uncomment the following line to fix the error.
// int C::s;
int main() {
C c;
C::s = 1;
}
宣告參數不符合定義
叫用函式範本的程式代碼必須具有相符的函式範本宣告。 宣告必須包含相同的樣板參數做為定義。 下列範例會在使用者定義的運算子上產生 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 main() {
Test<int> t;
cout << "Test: " << t << endl; // LNK2019 unresolved external
}
類型定義不一致wchar_t
此範例會建立 DLL,具有使用 WCHAR
的匯出,其解析為 wchar_t
。
// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}
下一個範例會使用上一個範例中的 DLL,併產生LNK2019,因為型 unsigned short*
別和 WCHAR*
不同。
// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);
int main() {
func(0);
}
若要修正此錯誤,請變更 unsigned short
為 wchar_t
或 WCHAR
,或使用 編譯 LNK2019g.cpp /Zc:wchar_t-
。
另請參閱
如需LNK2019、LNK2001和LNK1120錯誤之可能原因和解決方案的詳細資訊,請參閱 Stack Overflow 問題: What is an undefined reference/unresolved external symbol error and how do I fix it?
。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應