Linkertoolfehler LNK2001

nicht aufgelöstes externes Symbol "Symbol"

Der kompilierte Code verweist oder ruft das Symbol auf. Das Symbol ist nicht in Bibliotheken oder Objektdateien definiert, die vom Linker durchsucht werden.

Auf diese Fehlermeldung folgt ein schwerwiegender Fehler LNK1120. Um Fehler LNK1120 zu beheben, beheben Sie zunächst alle LNK2001 und LNK2019 Fehler.

Es gibt viele Möglichkeiten, LNK2001 Fehler zu erhalten. Alle enthalten einen Verweis auf eine Funktion oder Variable, die der Linker nicht auflösen kann, oder eine Definition finden kann. Der Compiler kann identifizieren, wenn ihr Code kein Symbol deklariert , aber nicht, wenn er kein Symbol definiert . Das liegt daran, dass sich die Definition möglicherweise in einer anderen Quelldatei oder -bibliothek befindet. Wenn ihr Code auf ein Symbol verweist, aber nie definiert ist, generiert der Linker einen Fehler.

Was ist ein nicht aufgelöstes externes Symbol?

Ein Symbol ist der interne Name für eine Funktion oder globale Variable. Es ist die Form des Namens, der in einer kompilierten Objektdatei oder -bibliothek verwendet oder definiert wird. Eine globale Variable wird in der Objektdatei definiert, in der der Speicher zugewiesen ist. Eine Funktion wird in der Objektdatei definiert, in der der kompilierte Code für den Funktionstext platziert wird. Ein externes Symbol ist ein Symbol , auf das in einer Objektdatei verwiesen wird, aber in einer anderen Bibliothek oder Objektdatei definiert ist. Ein exportiertes Symbol ist ein Symbol , das von der Objektdatei oder -bibliothek öffentlich zur Verfügung gestellt wird, die es definiert.

Zum Erstellen einer Anwendung oder DLL muss jedes verwendete Symbol über eine Definition verfügen. Der Linker muss die entsprechende Definition für jedes externe Symbol auflösen, auf das von jeder Objektdatei verwiesen wird. Der Linker generiert einen Fehler, wenn es kein externes Symbol auflösen kann. Dies bedeutet, dass der Linker in keiner der verknüpften Dateien eine übereinstimmende exportierte Symboldefinition finden konnte.

Dieser Fehler kann auftreten:

  • Wenn dem Projekt ein Verweis auf eine Bibliothek fehlt (. LIB) oder Objekt (. OBJ) Datei. Um dieses Problem zu beheben, fügen Sie Ihrem Projekt einen Verweis auf die erforderliche Bibliothek oder Objektdatei hinzu. Weitere Informationen finden Sie unter "Dateien als Linkereingabe".

  • Wenn das Projekt einen Verweis auf eine Bibliothek hat (. LIB) oder Objekt (. OBJ)-Datei, die wiederum Symbole aus einer anderen Bibliothek erfordert. Es kann vorkommen, auch wenn Sie keine Funktionen aufrufen, die die Abhängigkeit verursachen. Um dieses Problem zu beheben, fügen Sie Ihrem Projekt einen Verweis auf die andere Bibliothek hinzu. Weitere Informationen finden Sie unter Understanding the classic model for linking: Taking symbols along for the ride.

  • Wenn Sie die /NODEFAULTLIB - oder /Zl-Optionen verwenden. Wenn Sie diese Optionen angeben, werden Bibliotheken, die erforderlichen Code enthalten, nicht mit dem Projekt verknüpft, es sei denn, Sie haben sie explizit eingeschlossen. Um dieses Problem zu beheben, schließen Sie explizit alle Bibliotheken ein, die Sie in der Befehlszeile für Links verwenden. Wenn beim Verwenden dieser Optionen viele fehlende CRT- oder Standardbibliotheksfunktionsnamen angezeigt werden, schließen Sie explizit die CRT- und Standardbibliotheks-DLLs oder Bibliotheksdateien in den Link ein.

  • Wenn Sie die Option "/clr " kompilieren. Möglicherweise fehlt ein Verweis auf .cctor. Weitere Informationen zum Beheben dieses Problems finden Sie unter Initialisierung gemischter Assemblys.

  • Wenn Sie beim Erstellen einer Debugversion einer Anwendung eine Verknüpfung mit den Versionsmodusbibliotheken herstellen. Wenn Sie optionen /MTd oder /MDd verwenden oder definieren _DEBUG und dann mit den Releasebibliotheken verknüpfen, sollten Sie unter anderem viele potenzielle, ungelöste Externe erwarten. Das Verknüpfen eines Releasemodusbuilds mit den Debugbibliotheken verursacht auch ähnliche Probleme. Um dieses Problem zu beheben, stellen Sie sicher, dass Sie die Debugbibliotheken in Ihren Debugbuilds und Einzelhandelsbibliotheken in Ihren Verkaufsbuilds verwenden.

  • Wenn ihr Code auf ein Symbol aus einer Bibliotheksversion verweist, Sie aber eine andere Version der Bibliothek verknüpfen. Im Allgemeinen können Sie keine Objektdateien oder Bibliotheken kombinieren, die für verschiedene Versionen des Compilers erstellt wurden. Die Bibliotheken, die in einer Version enthalten sind, können Symbole enthalten, die in den Bibliotheken, die in anderen Versionen enthalten sind, nicht gefunden werden können. Um dieses Problem zu beheben, erstellen Sie alle Objektdateien und Bibliotheken mit derselben Version des Compilers, bevor Sie sie miteinander verknüpfen. Weitere Informationen finden Sie unter C++-Binärkompatibilität zwischen Visual Studio-Versionen.

  • Wenn Bibliothekspfade veraltet sind. Im Dialogfeld "Toolsoptionen >> projekte > VC++-Verzeichnisse " können Sie unter der Auswahl der Bibliotheksdateien die Suchreihenfolge der Bibliothek ändern. Der Ordner "Linker" im Dialogfeld "Eigenschaftenseiten" des Projekts kann auch Pfade enthalten, die veraltet sein könnten.

  • Wenn ein neues Windows SDK installiert wird (möglicherweise an einem anderen Speicherort). Die Bibliothekssuchreihenfolge muss aktualisiert werden, um auf den neuen Speicherort zu verweisen. Normalerweise sollten Sie den Pfad zu neuen SDK-Include- und Lib-Verzeichnissen vor dem standardmäßigen Visual C++-Speicherort platzieren. Außerdem verweist ein Projekt, das eingebettete Pfade enthält, möglicherweise immer noch auf alte, aber veraltete Pfade. Aktualisieren Sie die Pfade für neue Funktionen, die von der neuen Version hinzugefügt wurden, die an einem anderen Speicherort installiert ist.

  • Wenn Sie an der Befehlszeile erstellen und eigene Umgebungsvariablen erstellt haben. Stellen Sie sicher, dass die Pfade zu Tools, Bibliotheken und Headerdateien zu einer konsistenten Version wechseln. Weitere Informationen finden Sie unter Verwenden des MSVC-Toolsets über die Befehlszeile.

Codierungsprobleme

Dieser Fehler kann die folgenden Ursachen haben:

  • Nicht übereinstimmender Fall in der Quellcode- oder Moduldefinitionsdatei (.def). Wenn Sie beispielsweise eine Variable var1 in einer C++-Quelldatei benennen und versuchen, wie in einer anderen auf sie VAR1 zuzugreifen, wird dieser Fehler generiert. Verwenden Sie zum Beheben dieses Problems konsistente Schreib- und Groß-/Kleinschreibungsnamen.

  • Ein Projekt, das funktionsinlining verwendet. Dies kann vorkommen, wenn Sie die Funktionen in inline einer Quelldatei und nicht in einer Headerdatei definieren. Inlinefunktionen können nicht außerhalb der Quelldatei angezeigt werden, die sie definiert. Um dieses Problem zu beheben, definieren Sie die inlineierten Funktionen in den Kopfzeilen, in denen sie deklariert sind.

  • Aufrufen einer C-Funktion aus einem C++-Programm ohne Verwenden einer extern "C" Deklaration für die C-Funktion. Der Compiler verwendet verschiedene interne Symbolbenennungskonventionen für C- und C++-Code. Der interne Symbolname ist das, wonach der Linker beim Auflösen von Symbolen sucht. Um dieses Problem zu beheben, verwenden Sie einen extern "C" Wrapper um alle Deklarationen von C-Funktionen, die in Ihrem C++-Code verwendet werden, wodurch der Compiler die interne C-Benennungskonvention für diese Symbole verwendet. Compileroptionen /Tp und /Tc führen dazu, dass der Compiler Dateien als C++ oder C kompiliert, unabhängig davon, was die Dateinamenerweiterung ist. Diese Optionen können dazu führen, dass sich interne Funktionsnamen von ihren Erwartungen unterscheiden.

  • Ein Versuch, auf Funktionen oder Daten zu verweisen, die keine externe Verknüpfung aufweisen. In C++ weisen Inlinefunktionen und const -daten interne Verknüpfungen auf, es sei denn, dies wird explizit als externangegeben. Um dieses Problem zu beheben, verwenden Sie explizite extern Deklarationen für Symbole, die außerhalb der definierenden Quelldatei verweisen.

  • Fehlende Funktionstext- oder Variablendefinition . Dieser Fehler tritt häufig auf, wenn Sie deklarieren, aber keine Variablen, Funktionen oder Klassen in Ihrem Code definieren. Der Compiler benötigt nur einen Funktionsprototyp oder extern eine Variable-Deklaration, um eine Objektdatei ohne Fehler zu generieren, der Linker kann jedoch keinen Aufruf der Funktion oder einen Verweis auf die Variable auflösen, da kein Funktionscode oder variablen Leerraum reserviert ist. Um dieses Problem zu beheben, müssen Sie jede referenzierte Funktion und Variable in einer Quelldatei oder Bibliothek definieren, die Sie verknüpfen.

  • Ein Funktionsaufruf, der Rückgabe- und Parametertypen oder Aufrufkonventionen verwendet, die nicht mit den in der Funktionsdefinition übereinstimmen. In C++-Objektdateien codiert name decoration die aufrufende Konvention, Klasse oder Namespacebereich sowie Rückgabe- und Parametertypen einer Funktion. Die codierte Zeichenfolge wird Teil des endgültigen eingerichteten Funktionsnamens. Dieser Name wird vom Linker verwendet, um Aufrufe der Funktion aus anderen Objektdateien aufzulösen oder abzugleichen. Um dieses Problem zu beheben, stellen Sie sicher, dass die Funktionsdeklaration, Definition und aufruft alle dieselben Bereiche, Typen und Aufrufkonventionen verwenden.

  • C++-Code, den Sie aufrufen, wenn Sie einen Funktionsprototyp in eine Klassendefinition einschließen, aber nicht die Implementierung der Funktion einschließen. Um dieses Problem zu beheben, stellen Sie sicher, dass Sie eine Definition für alle von Ihnen aufgerufenen Klassenmitglieder bereitstellen.

  • Ein Versuch, eine reine virtuelle Funktion aus einer abstrakten Basisklasse aufzurufen. Eine reine virtuelle Funktion hat keine Basisklassenimplementierung. Um dieses Problem zu beheben, stellen Sie sicher, dass alle aufgerufenen virtuellen Funktionen implementiert sind.

  • Es wird versucht, eine Variable zu verwenden, die innerhalb einer Funktion (einer lokalen Variablen) außerhalb des Gültigkeitsbereichs dieser Funktion deklariert ist. Um dieses Problem zu beheben, entfernen Sie den Verweis auf die Variable, die sich nicht im Bereich befindet, oder verschieben Sie die Variable in einen höheren Bereich.

  • Wenn Sie eine Releaseversion eines ATL-Projekts erstellen, wird eine Meldung erstellt, dass CRT-Startcode erforderlich ist. Führen Sie eine der folgenden Aktionen aus, um dieses Problem zu beheben:

    • Entfernen Sie _ATL_MIN_CRT aus der Liste der Präprozessordefinitionen, damit CRT-Startcode eingeschlossen werden kann. Weitere Informationen finden Sie auf der Seite "Allgemeine Eigenschaft" (Project).For more information, see General property page (Project).

    • Entfernen Sie nach Möglichkeit Aufrufe von CRT-Funktionen, die CRT-Startcode erfordern. Verwenden Sie stattdessen ihre Win32-Entsprechungen. Verwenden Sie z. B. lstrcmp statt strcmp. Bekannte Funktionen, die CRT-Startcode erfordern, sind einige der Zeichenfolgen- und Gleitkommafunktionen.

Konsistenzprobleme

Derzeit gibt es keinen Standard für die C++-Namensgestaltung zwischen Compileranbietern oder sogar zwischen verschiedenen Versionen desselben Compilers. Objektdateien, die mit verschiedenen Compilern kompiliert wurden, verwenden möglicherweise nicht dasselbe Benennungsschema. Das Verknüpfen kann zu fehler LNK2001 führen.

Das Mischen von Inline- und Nicht-Inlinekompilierungsoptionen für verschiedene Module kann LNK2001 verursachen. Wenn eine C++-Bibliothek mit aktivierter Funktion (/Ob1 oder /Ob2) erstellt wird, aber die entsprechende Headerdatei, in der die Funktionen beschrieben wird, deaktiviert ist (keine inline Schlüsselwort (keyword)), tritt dieser Fehler auf. Um dieses Problem zu beheben, definieren Sie die Funktionen inline in der Headerdatei, die Sie in andere Quelldateien einschließen.

Wenn Sie die #pragma inline_depth Compilerdirektive verwenden, stellen Sie sicher, dass Sie einen Wert von 2 oder höher festgelegt haben, und stellen Sie sicher, dass Sie auch die Compileroption "/Ob1 " oder "/Ob2 " verwenden.

Dieser Fehler kann auftreten, wenn Sie die LINK-Option /NOENTRY weglassen, wenn Sie eine nur-Ressourcen-DLL erstellen. Um dieses Problem zu beheben, fügen Sie der Verknüpfungsbefehl die Option "/NOENTRY" hinzu.

Dieser Fehler kann auftreten, wenn Sie falsche /SUBSYSTEM- oder /ENTRY-Einstellungen in Ihrem Projekt verwenden. Wenn Sie beispielsweise eine Konsolenanwendung schreiben und /SUBSYSTEM:WINDOWS angeben, wird ein nicht behobener externer Fehler generiert WinMain. Um dieses Problem zu beheben, stellen Sie sicher, dass Sie den Optionen des Projekttyps entsprechen. Weitere Informationen zu diesen Optionen und Einstiegspunkten finden Sie in den Optionen /SUBSYSTEM und /ENTRY linker.

Probleme mit exportierten DEF-Dateisymbolen

Dieser Fehler tritt auf, wenn ein in einer DEF-Datei aufgelisteter Export nicht gefunden wird. Dies könnte darauf zurückzuführen sein, dass der Export nicht vorhanden ist, falsch geschrieben ist oder C++-versehene Namen verwendet. Eine DEF-Datei enthält keine versehenen Namen. Um dieses Problem zu beheben, entfernen Sie nicht benötigte Exporte, und verwenden Sie extern "C" Deklarationen für exportierte Symbole.

Verwenden Sie den eingerichteten Namen, um den Fehler zu finden.

Der C++-Compiler und Linker verwenden namens Decoration, auch bekannt als Name-Mangling. Die Namensgestaltung codiert zusätzliche Informationen zum Typ einer Variablen im Symbolnamen. Der Symbolname einer Funktion codiert den Rückgabetyp, Parametertypen, Bereichs- und Aufrufkonventionen. Dieser verzierte Name ist der Symbolname, nach dem der Linker sucht, um externe Symbole aufzulösen.

Ein Verknüpfungsfehler kann dazu führen, dass die Deklaration einer Funktion oder Variable nicht exakt mit der Definition der Funktion oder Variable übereinstimmt. Das liegt daran, dass jeder Unterschied Teil des Zugleichenden Symbolnamens wird. Der Fehler kann auch dann auftreten, wenn die gleiche Headerdatei sowohl im aufrufenden Code als auch im definierenden Code verwendet wird. Eine Möglichkeit kann auftreten, wenn Sie die Quelldateien mithilfe verschiedener Compilerflags kompilieren. Wenn Ihr Code beispielsweise für die Verwendung der __vectorcall Aufrufkonvention kompiliert wird, Sie jedoch eine Verknüpfung mit einer Bibliothek herstellen, die erwartet, dass Clients sie mit der Standard- __cdecl oder __fastcall Anrufkonvention aufrufen. In diesem Fall stimmen die Symbole nicht überein, da die Aufrufkonventionen unterschiedlich sind.

Um die Ursache zu finden, zeigt die Fehlermeldung zwei Versionen des Namens an. Er zeigt sowohl den "Anzeigenamen", den im Quellcode verwendeten Namen als auch den verzierten Namen (in Klammern) an. Sie müssen nicht wissen, wie Sie den verzierten Namen interpretieren. Sie können sie weiterhin mit anderen verzierten Namen suchen und vergleichen. Befehlszeilentools können dabei helfen, den erwarteten Symbolnamen und den tatsächlichen Symbolnamen zu finden und zu vergleichen:

  • Die Optionen /EXPORTS und /SYMBOLS des DUMPBIN-Befehlszeilentools sind hier hilfreich. Sie können Ihnen helfen, zu ermitteln, welche Symbole in Ihren DLL- und Objekt- oder Bibliotheksdateien definiert sind. Sie können die Symbolliste verwenden, um zu überprüfen, ob die exportierten versehenen Namen mit den versehenen Namen übereinstimmen, nach denen der Linker sucht.

  • In einigen Fällen kann der Linker nur den versehenen Namen für ein Symbol melden. Sie können das Befehlszeilentool UNDNAME verwenden, um die nicht ausgestaltete Form eines verzierten Namens abzurufen.

Zusätzliche Ressourcen

Weitere Informationen finden Sie in der Stack Overflow-Frage "Was ist ein nicht definierter Verweis/nicht aufgelöster externer Symbolfehler und wie kann ich es beheben?".