Linkertoolfehler LNK2019
Nicht aufgelöstes externes Symbol "Symbol", auf das in der Funktion "Funktion" verwiesen wird
Der kompilierte Code für function verweist auf symbol oder ruft es auf, der Linker kann jedoch die Symboldefinition in keiner der Bibliotheken oder Objektdateien finden.
Dieser Fehlermeldung folgt der schwerwiegende Fehler LNK1120. Zum Beheben des LNK1120-Fehlers müssen Sie zuerst alle LNK2001- und LNK2019-Fehler beheben.
Mögliche Ursachen
Es gibt viele Möglichkeiten, die zum Auftreten dieses Fehlers führen können. Alle umfassen einen Verweis auf eine Funktion oder Variable, die der Linker nicht auflösen oder für die er keine Definition finden konnte. Der Compiler kann identifizieren, wenn ein Symbol nicht deklariert ist, er kann aber nicht erkennen, wenn das Symbol nicht definiert ist. Dies liegt daran, dass sich die Definition möglicherweise in einer anderen Quelldatei oder -bibliothek befindet. Wenn auf ein Symbol verwiesen, aber nie definiert wird, generiert der Linker einen nicht aufgelösten externen Symbolfehler.
Hier sind einige der häufigsten Probleme aufgeführt, die zum Fehler LNK2019 führen:
Die Quelldatei, die die Definition dieses Symbols enthält, wird nicht kompiliert.
Stellen Sie in Visual Studio sicher, dass die Quelldatei, die das Symbol definiert, im Rahmen Ihres Projekts kompiliert wird. Überprüfen Sie das Zwischenausgabeverzeichnis des Builds auf eine übereinstimmende .obj-Datei. Wenn die Quelldatei nicht kompiliert wird, klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die Datei, und wählen Sie dann Eigenschaften aus, um die Eigenschaften der Datei zu überprüfen. Auf der Seite Konfigurationseigenschaften>Allgemeinen sollte ein Elementtyp des C/C++-Compilers angezeigt werden. Stellen Sie in der Befehlszeile sicher, dass die Quelldatei, die die Definition enthält, kompiliert wird.
Die Objektdatei oder -bibliothek, die die Definition des Symbols enthält, wird nicht verknüpft.
Stellen Sie in Visual Studio sicher, dass Sie die Objektdatei oder -bibliothek, die die Symboldefinition enthält, im Rahmen Ihres Projekts verknüpfen. Stellen Sie in der Befehlszeile sicher, dass die Liste der zu verknüpfenden Dateien die Objektdatei oder -bibliothek umfasst.
Die Schreibweise der Symboldeklaration stimmt nicht mit der Definition des Symbols überein.
Stellen Sie sicher, dass Sie sowohl in der Deklaration als auch in der Definition und überall, wo das Symbol verwendet oder aufgerufen wird, die korrekte Schreibweise und Groß-/Kleinschreibung verwenden.
Eine Funktion wird verwendet, aber der Typ oder die Anzahl der Parameter stimmen nicht mit der Funktionsdefinition überein.
Die Funktionsdeklaration muss mit die Definition übereinstimmen. Stellen Sie sicher, dass der Funktionsaufruf der Deklaration entspricht und dass die Deklaration mit der Definition übereinstimmt. Für Code, der Funktionsvorlagen aufruft, sind auch entsprechende Deklarationen der Funktionsvorlagen erforderlich, die dieselben Vorlagenparameter wie die Definition enthalten. Ein Beispiel für eine einen Konflikt mit einer Vorlagendeklaration finden Sie im Beispiel LNK2019e.cpp im Abschnitt „Beispiele“.
Eine Funktion oder Variable wurde deklariert, aber nicht definiert.
Der Fehler LNK2019 kann auftreten, wenn in der Headerdatei eine Deklaration vorhanden ist, jedoch keine entsprechende Definition implementiert wurde. Für Memberfunktionen oder static-Datenmember muss die Implementierung die Klassenbereichsauswahl enthalten. Ein Beispiel finden Sie unter Missing Function Body or Variable.
Die Aufrufkonvention unterscheidet sich zwischen der Deklaration und der Definition der Funktion.
Einige Aufrufkonventionen (__cdecl
, __stdcall
, __fastcall
und __vectorcall
) werden als Teil des ergänzten Namens codiert. Stellen Sie sicher, dass die Aufrufkonvention identisch ist.
Ein Symbol ist in einer C-Datei definiert, wurde aber ohne Verwendung von extern "C"
in einer C++-Datei deklariert.
Eine Datei, die als C kompiliert wird, erstellt versehene Namen, für symbols die sich von den dekorierten Namen für dieselbe symbols in einer C++-Datei deklarierte Namen unterscheiden, es sei denn, Sie verwenden einen extern "C"
Modifizierer. Stellen Sie sicher, dass die Deklaration der Kompilierungsverknüpfung für jedes Symbol entspricht. Auch wenn Sie ein Symbol in einer C++-Datei definieren, die von einem C-Programm verwendet wird, verwenden Sie extern "C"
in der Definition.
Ein Symbol wird als static definiert und später außerhalb der Datei referenziert.
Anders als in C, verfügen globale Konstanten in C++ über eine static
-Verknüpfung. Um diese Einschränkung zu umgehen, können Sie die const
-Initialisierungen in eine Headerdatei einfügen und diesen Header anschließend in die CPP-Dateien einfügen, oder Sie deklarieren die Variable als nicht konstant und verwenden einen konstanten Verweis, um darauf zuzugreifen.
Ein static-Member einer Klasse ist nicht definiert.
Ein static-Klassenmember muss eine eindeutige Definition aufweisen, da ansonsten die ODR (One Definition Rule) verletzt wird. Ein static-Klassenmember, der nicht inline definiert werden kann, muss anhand seines vollqualifizierten Namens in einer Quelldatei definiert werden. Wenn er überhaupt nicht definiert wird, generiert er den Fehler LNK2019.
Eine Buildabhängigkeit wird in der Projektmappe nur als Projektabhängigkeit definiert.
In früheren Versionen von Visual Studio war diese Ebene der Abhängigkeit ausreichend. Ab Visual Studio 2010 erfordert Visual Studio jedoch einen Interprojektverweis. Wenn Ihr Projekt keinen Interprojektverweis enthält, wird dieser Linkerfehler möglicherweise angezeigt. Fügen Sie einen Interprojektverweis hinzu, um den Fehler zu beheben.
Ein Einstiegspunkt ist nicht definiert.
Der Anwendungscode muss einen geeigneten Einstiegspunkt definieren: main
oder wmain
für Konsolenanwendungen und WinMain
oder wWinMain
für Windows-Anwendungen. Weitere Informationen finden Sie unter main
-Funktion und Befehlszeilenargumente oder unter WinMain
-Funktion. Um einen benutzerdefinierten Einstiegspunkt zu verwenden, geben Sie die Linkeroption /ENTRY
(Einstiegspunktsymbol) an.
Sie erstellen eine Konsolenanwendung mithilfe von Einstellungen für eine Windows-Anwendung.
Wenn die Fehlermeldung dem nicht aufgelösten externen Symbol WinMain ähnelt, auf das in Funktion function_name verwiesen wird, verwenden Sie die Verknüpfung /SUBSYSTEM:CONSOLE
anstelle von /SUBSYSTEM:WINDOWS
. Weitere Informationen zu dieser Einstellung sowie Anweisungen zum Festlegen dieser Eigenschaft in Visual Studio finden Sie unter /SUBSYSTEM
(Subsystem angeben).
Sie versuchen, 64-Bit-Bibliotheken mit 32-Bit-Code oder 32-Bit-Bibliotheken mit 64-Bit-Code zu verknüpfen.
Bibliotheken und Objektdateien, die mit Ihrem Code verknüpft sind, müssen für dieselbe Architektur wie Ihr Code kompiliert werden. Stellen Sie sicher, dass die Bibliotheken, auf die Ihre Projektverweise verweisen, für dieselbe Architektur wie Ihr Projekt kompiliert werden. Stellen Sie sicher, dass die /LIBPATH
- oder Additional Libary Directories-Eigenschaft (zusätzliche Bibliotheksverzeichnisse) auf Bibliotheken verweist, die für die entsprechende Architektur erstellt wurden.
Sie verwenden verschiedene Compileroptionen für Inlinefunktionen in anderen Quelldateien.
Durch die Verwendung von Inlinefunktionen, die in CPP-Dateien definiert sind, und die Kombination von Inlinecompileroptionen für Funktionen in anderen Quelldateien kann LNK2019 verursacht werden. Weitere Informationen finden Sie unter Function Inlining Problems.
Sie verwenden automatische Variablen außerhalb ihres Bereichs.
Automatische Variablen (mit Funktionsgültigkeitsbereich) können nur im Rahmen dieser Funktion verwendet werden. Diese Variablen können nicht extern
deklariert und in anderen Quelldateien verwendet werden. Ein Beispiel finden Sie unter Automatic (Function Scope) Variables.
Sie rufen intrinsische Funktionen auf oder übergeben Argumenttypen an intrinsische Funktionen, die auf der Zielarchitektur nicht unterstützt werden.
Wenn Sie z. B. eine AVX2 systeminterne Option verwenden, aber nicht die /ARCH:AVX2
Compileroption angeben, geht der Compiler davon aus, dass es sich bei der systeminternen Funktion um eine externe Funktion handelt. Anstelle einer Inlineanweisung generiert der Compiler einen Aufruf an ein externes Symbol mit demselben Namen wie die intrinsische Funktion. Wenn der Linker versucht, die Definition dieser fehlende Funktion zu finden, wird LNK2019 generiert. Stellen Sie sicher, dass Sie nur intrinsische Funktionen und Typen verwenden, die von der Zielarchitektur unterstützt werden.
Sie kombinieren Code, der den nativen wchar_t
-Typ verwendet, mit Code, der dies nicht tut.
Durch die in Visual Studio 2005 vorgenommene Konformitätsverbesserung der C++-Sprache wurde wchar_t
standardmäßig als nativer Typ festgelegt. Wenn nicht alle Dateien mit denselben /Zc:wchar_t
-Einstellungen kompiliert wurden, werden Typenverweise möglicherweise nicht in kompatible Typen aufgelöst. Stellen Sie sicher, dass wchar_t
-Typen in allen Bibliotheks- und Objektdateien kompatibel sind. Aktualisieren Sie entweder von einem wchar_t
-Typedef, oder verwenden Sie beim Kompilieren konsistente /Zc:wchar_t Einstellungen.
Beim Verknüpfen einer static-Legacy-Bibliothek erhalten Sie Fehler für *printf*
- und *scanf*
-Funktionen.
Eine static-Bibliothek, die mit einer Version von Visual Studio vor Visual Studio 2015 erstellt wurde, kann möglicherweise LNK2019-Fehler verursachen, wenn sie mit der UCRT verknüpft ist. Die UCRT-Headerdateien <stdio.h>
, <conio.h>
und <wchar.h>
definieren jetzt viele Variationen von*printf*
und *scanf*
als inline
-Funktionen. Die Inlinefunktionen werden durch eine kleinere Gruppe gängiger Funktionen implementiert. Die Einzelnen exports für die inlineierten Funktionen sind in den Standard-UCRT-Bibliotheken nicht verfügbar, die nur die allgemeinen Funktionen exportieren. Es gibt mehrere Möglichkeiten, dieses Problem zu beheben. Es wird empfohlen, die Legacy-Bibliothek mithilfe Ihrer aktuellen Version von Visual Studio neu zu erstellen. Stellen Sie sicher, dass der Bibliothekscode die Standardheader für die Definitionen der *printf*
- und *scanf*
-Funktionen, die die Fehler verursacht haben, verwendet. Eine weitere Option für eine Legacy-Bibliothek, die Sie nicht neu erstellen können, besteht darin, legacy_stdio_definitions.lib
zur Liste der Bibliotheken hinzuzufügen, die Sie verknüpfen. Diese Bibliotheksdatei stellt symbols die *printf*
inlineierten Funktionen in *scanf*
den UCRT-Headern bereit. Weitere Informationen finden Sie in der im Abschnitt Bibliotheken im Überblick über potenzielle Upgradeprobleme.
Probleme mit Bibliotheken von Drittanbietern und vcpkg
Wenn dieser Fehler beim Versuch angezeigt wird, die Bibliothek eines Drittanbieters als Teil Ihres Builds zu konfigurieren, sollten Sie vcpkgverwenden. vcpkg ist ein C++-Paket-Manager, der Ihre vorhandenen Visual Studio-Tools zum Installieren und Erstellen der Bibliothek verwendet. vcpkg unterstützt eine große und wachsende Liste von Bibliotheken von Drittanbietern. Der Paket-Manager legt alle Konfigurationseigenschaften und Abhängigkeiten fest, die für erfolgreiche Builds im Rahmen Ihres Projekts erforderlich sind.
Diagnosetools
Manchmal ist es schwierig, festzustellen, warum der Linker eine bestimmte Symboldefinition nicht finden kann. Häufig besteht das Problem darin, dass Sie den Code, der die Definition enthält, nicht in ihren Build eingeschlossen haben. Oder Buildoptionen haben verschiedene verzierte Namen für externe symbolsDateien erstellt. Es gibt mehrere Tools und Optionen, mit denen Sie einen LNK2019-Fehler diagnostizieren können.
Mithilfe der Linkeroption
/VERBOSE
können Sie ermitteln, auf welche Dateien der Linker verweist. Mithilfe dieser Option können Sie überprüfen, ob die Datei mit der Definition des Symbols in Ihrem Build enthalten ist.Mit
/EXPORTS
den Optionen/SYMBOLS
und Optionen des DUMPBIN Hilfsprogramms können Sie ermitteln, welche symbols in Ihren .dll- und Objekt- oder Bibliotheksdateien definiert sind. Stellen Sie sicher, dass die exportierten ergänzten Namen den ergänzten Namen entsprechen, die vom Linker gesucht werden.Das UNDNAME Hilfsprogramm kann Ihnen das entsprechende, nicht ausgestaltete externe Symbol für einen verzierten Namen anzeigen.
Beispiele
Hier sind einige Beispiele für Code aufgeführt, der einen LNK2019-Fehler verursacht, sowie Informationen zur Behebung des Fehlers.
Ein Symbol wurde deklariert, aber nicht definiert
In diesem Beispiel wird eine externe Variable deklariert, aber nicht definiert:
// 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
}
Hier ist ein weiteres Beispiel, in dem eine Variable und Funktion als extern
deklariert werden, jedoch keine Definition bereitgestellt wird:
// LNK2019c.cpp
// Compile by using: cl /EHsc LNK2019c.cpp
// LNK2019 expected
extern int i;
extern void g();
void f() {
i++;
g();
}
int main() {}
Wenn i
und g
nicht in einer der im Build enthaltenen Dateien definiert wurden, generiert der Linker einen LNK2019-Fehler. Sie können die Fehler beheben, indem Sie die Quellcodedatei mit den Definitionen in die Kompilierung einbeziehen. Alternativ können Sie .obj
- oder .lib
-Dateien, die die Definitionen enthalten, an den Linker übergeben.
Ein static Datenmember wurde deklariert, aber nicht definiert.
Ein LNK2019-Fehler kann auch auftreten, wenn ein static Datenmember deklariert, aber nicht definiert wurde. Im folgenden Beispiel wird LNK2019 generiert und gezeigt, wie Sie diesen Fehler beheben.
// 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;
}
Deklarationsparameter stimmen nicht mit der Definition überein
Code, der Funktionsvorlagen aufruft, muss übereinstimmende Deklarationen von Funktionsvorlagen aufweisen. Deklarationen müssen dieselben Vorlagenparameter wie die Definition enthalten. Das folgende Beispiel generiert LNK2019 für einen benutzerdefinierten Operator und zeigt, wie Sie diesen Fehler beheben.
// 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
}
Inkonsistente wchar_t-Typdefinitionen
Dieses Beispiel erstellt eine DLL mit einem Export, der einen WCHAR
verwendet, der in wchar_t
aufgelöst wird.
// LNK2019g.cpp
// compile with: cl /EHsc /LD LNK2019g.cpp
#include "windows.h"
// WCHAR resolves to wchar_t
__declspec(dllexport) void func(WCHAR*) {}
Im nächsten Beispiel wird die DLL aus dem vorherigen Beispiel verwendet und generiert einen LNK2019-Fehler, da die Typen unsigned short*
und WCHAR*
nicht identisch sind.
// LNK2019h.cpp
// compile by using: cl /EHsc LNK2019h LNK2019g.lib
// LNK2019 expected
__declspec(dllimport) void func(unsigned short*);
int main() {
func(0);
}
Um diesen Fehler zu beheben, ändern Sie unsigned short
in wchar_t
oder WCHAR
, oder kompilieren Sie die Datei „LNK2019g.cpp“ mithilfe von /Zc:wchar_t-
.
Weitere Informationen
Weitere Informationen zu möglichen Ursachen und Lösungen für die LNK2019-, LNK2001- und LNK1120-Fehler finden Sie in folgender Stack Overflow-Frage: What is an undefined reference/unresolved external symbol error and how do I fix it?
.