Freigeben über


Linkertoolfehler LNK2019

nicht aufgelöstes externes Symbol 'symbol' in Funktion 'funktion' referenziert

Der Linker konnte für das externe Symbol "symbol", das in der Funktion "function" verwendet wird, keine Definition finden. Es gibt viele Probleme, die diesen Fehler verursachen können. Dieses Thema hilft Ihnen dabei, die Ursache zu identifizieren und eine Lösung zu finden.

Ein externes Symbol ist der deklarierte Name, mit dem Sie im Quellcode auf ein Element verweisen, das in einem anderen Modul definiert ist, z. B. eine externe Funktion oder eine globale Variable. Der Linker ist für die Auflösung aller externen Symbolverweise in den einzelnen Modulen zuständig, wenn diese in einer Anwendung oder DLL verknüpft sind. Wenn der Linker in keiner der verknüpften Dateien eine entsprechende Definition für ein externes Symbol finden kann, wird LNK2019 generiert. Dieser Fehler kann auftreten, wenn der Quellcode oder die Bibliotheksdatei mit der Definition des Symbols nicht im Build enthalten ist. Er kann außerdem dann auftreten, wenn der vom Linker gesuchte Name nicht mit dem Namen des Symbols in dem Modul übereinstimmt, in dem es definiert ist.

Code mit C++-Bindung verwendet Namensergänzung, auch bekannt als Name-Mangling, um zusammen mit dem Symbolnamen zusätzliche Informationen über den Typ und die Aufrufkonvention eines Symbols zu codieren. Der ergänzte Name ist der Name, der vom Linker zum Auflösen externer Symbole gesucht wird. Da der Deklarationstyp des Symbolverweises Teil des ergänzten Symbolnamens wird, wird der Fehler LNK2019 möglicherweise verursacht, wenn dieser Deklarationstyp nicht mit dem Deklarationstyp der Symboldefinition übereinstimmt. In der Fehlermeldung werden sowohl das externe Symbol als auch der ergänzte Name angezeigt, damit Sie die Ursache des Fehlers ermitteln können.

Häufig auftretende Probleme

Hier sind einige der häufigsten Probleme aufgeführt, die zum Fehler LNK2019 führen:

  • Die Schreibweise der Symboldeklaration stimmt nicht mit der Definition des Symbols überein. Stellen Sie sicher, dass die richtige Schreibweise verwendet wurde.

  • 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. Für Code, der Vorlagenfunktionen aufruft, sind auch entsprechende Deklarationen der Vorlagenfunktionen erforderlich, die dieselben Vorlagenparameter wie die Definition enthalten. Stellen Sie sicher, dass der Funktionsaufruf der Deklaration entspricht und dass die Deklaration mit der Definition übereinstimmt.

  • Eine Funktion oder Variable wurde deklariert, aber nicht definiert. Ein Beispiel hierzu finden Sie unter Fehlender Funktionsrumpf oder fehlende Variable.

  • Die Aufrufkonvention unterscheidet sich zwischen der Deklaration und der Definition der Funktion. Aufrufkonventionen (__cdecl, __stdcall, __fastcall oder __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. Symbole, die in einer in C kompilierten Datei definiert sind, besitzen andere ergänzte Namen als Symbole, die in einer C++-Datei deklariert werden, 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 statischer Member einer Klasse wurde nicht definiert. Ein statischer Klassenmember muss eine eindeutige Definition aufweisen, da ansonsten ODR (One Definition Rule) verletzt wird. Ein statischer Klassenmember, der nicht inline definiert werden kann, muss anhand seines vollqualifizierten Namens in einem Modul definiert werden. Wenn er überhaupt nicht definiert wird, generiert der Linker 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.

  • Sie erstellen eine Konsolenanwendung anhand von Einstellungen für eine Windows-Anwendung. Wenn die Fehlermeldung unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup lautet, verknüpfen Sie über /SUBSYSTEM:CONSOLE anstelle von /SUBSYSTEM:WINDOWS. Weitere Informationen zu dieser Einstellung und Anweisungen zum Festlegen dieser Eigenschaft in Visual Studio finden Sie unter /SUBSYSTEM (Subsystem angeben).

  • Sie verwenden verschiedene Compileroptionen für Inlinefunktionen in anderen Modulen. Durch die Verwendung von Inlinefunktionen, die in CPP-Dateien definiert sind, und die Kombination von Inlinecompileroptionen für Funktionen in anderen Modulen kann LNK2019 verursacht werden. Weitere Informationen hierzu finden Sie unter Probleme bei Inlinefunktionen.

  • 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 Modulen verwendet werden. Ein Beispiel hierfür finden Sie unter Automatische Variablen (mit Funktionsgültigkeitsbereich).

  • Sie rufen intrinsische Funktionen auf oder übergeben Argumenttypen an intrinsische Funktionen, die auf der Zielarchitektur nicht unterstützt werden. Wenn Sie beispielsweise eine intrinsische AVX2-Funktion verwenden, aber nicht die Compileroption /ARCH:AVX2 angeben, nimmt der Compiler an, dass es sich bei der intrinsischen 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 mit dem systemeigenen Datentyp "wchar_t" mit Code, der diesen Datentyp nicht verwendet. Durch die in Visual C++ 2005 vorgenommene Konformitätsverbesserung der C++-Sprache wurde wchar_t standardmäßig als systemeigener Typ festgelegt. Sie müssen die Compileroption /Zc:wchar_t- zum Generieren von Code verwenden, der mit Modulen kompatibel ist, die mit früheren Versionen von Visual C++ kompiliert wurde. Wenn nicht alle Module mit denselben /Zc:wchar_t-Einstellungen kompiliert wurden, werden Typenverweise möglicherweise nicht in kompatible Typen aufgelöst. Überprüfen Sie, ob wchar_t-Typen in allen Modulen kompatibel sind. Aktualisieren Sie hierzu entweder die verwendeten Typen, oder verwenden Sie bei Kompilieren konsistente /Zc:wchar_t-Einstellungen.

Weitere Informationen zu möglichen Ursachen und Lösungen für LNK2019 finden Sie in der Stapelüberlauf-Frage Was ist ein Fehler durch einen nicht definierten Verweis/ein nicht aufgelöstes externes Symbol, und wie löse ich dieses Problem?.

Diagnosetools

Es kann schwierig sein festzustellen, warum der Linker eine bestimmte Symboldefinition nicht finden kann. Häufig besteht das Problem darin, dass Sie den Code nicht in Ihren Build einbezogen haben oder dass durch Buildoptionen andere ergänzte Namen für externe Symbole erstellt wurden. Es gibt mehrere Tools und Optionen, mit denen Sie einen Fehler LNK2019 diagnostizieren können.

  • Mithilfe der Linkeroption /VERBOSE können Sie ermitteln, auf welche Dateien der Linker verweist. Damit können Sie überprüfen, ob die Datei mit der Definition des Symbols in Ihrem Build enthalten ist.

  • Anhand der Optionen /EXPORTS und /SYMBOLS des DUMPBIN-Hilfsprogramms können Sie ermitteln, welche Symbole in den 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 Hilfsprogramm UNDNAME kann Ihnen das entsprechende nicht ergänzte externe Symbol für einen ergänzten Namen anzeigen.

Beispiele

Hier sind einige Beispiele für Code aufgeführt, der einen Fehler LNK2019 verursacht, sowie Informationen zur Behebung des Fehlers.

Ein Symbol wurde deklariert, aber nicht definiert

Im folgenden Beispiel wird LNK2019 generiert, da ein externes Symbol deklariert, aber nicht definiert wurde:

// LNK2019.cpp
// Compile by using: cl /EHsc LNK2019.cpp
// LNK2019 expected
extern char B[100];   // B is not available to the linker
int main() {
   B[0] = ' ';   // LNK2019
}

Hier sehen Sie ein weiteres Beispiel:

// 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 Dateien im Build definiert wurden, generiert der Linker LNK2019. 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 statischer Datenmember wurde deklariert, aber nicht definiert

LNK2019 kann auch auftreten, wenn ein statischer 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 Definition überein

Code, der Vorlagenfunktionen aufruft, muss übereinstimmende Deklarationen von Vorlagenfunktionen 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 does not 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

Im folgenden Beispiel wird eine DLL mit einem Export erstellt, 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 folgenden Beispiel wird die DLL aus dem vorherigen Beispiel verwendet und LNK2019 generiert, 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 "LNK2019g.cpp" über /Zc:wchar_t-.