Nicht aufgelöstes externes Symbol in Objektdateien

180

Während des Codierens in Visual Studio ist ein ungelöster Fehler mit externen Symbolen aufgetreten, und ich habe keine Ahnung, was ich tun soll. Ich weiss nicht, was falsch ist. Könnten Sie mich bitte entziffern? Wo soll ich nach welchen Fehlern suchen?

1>Form.obj : error LNK2019: unresolved external symbol "public: class Field * __thiscall Field::addField(class Field *)" (?addField@Field@@QAEPAV1@PAV1@@Z) referenced in function "public: void __thiscall Form::parse(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?parse@Form@@QAEXAAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>Form.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall Field::parse(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (?parse@Field@@UAEXAAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: __thiscall InputField::InputField(class std::basic_stringstream<char,struct std::char_traits<char>,class std::allocator<char> > &)" (??0InputField@@QAE@AAV?$basic_stringstream@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Field::prompt(void)" (?prompt@Field@@UAEXXZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Field::getName(void)" (?getName@Field@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Field::getType(void)" (?getType@Field@@UAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>Form.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Field::describe(void)" (?describe@Field@@UAEXXZ)
1>C:\Users\tomy\Documents\Visual Studio 2010\Projects\zapoctovkac++\Debug\zapoctovkac++.exe : fatal error LNK1120: 6 unresolved externals
Novellizator
quelle
26
Ein ungelöstes Symbol ist eines, das Sie irgendwo deklariert, aber nie definiert haben. Normalerweise bedeutet dies, dass Sie die Header-Datei einer Drittanbieter-Bibliothek # eingeschlossen haben, dem Linker jedoch nicht mitgeteilt haben, wo sich die entsprechenden OBJ-Dateien für die Bibliothek befinden.
Deong
7
Ein ziemlich häufiger Fehler ist, dass Sie eine Funktion als eigenständig definieren und den Klassenselektor in Ihrer CPP- Datei vergessen : Sie tun dies (falsch): void myFunc() { /* do stuff */ } Stattdessen (richtig): void A::myFunc() { /* do stuff */ }
jave.web
Sie können Klammern auch direkt in Ihre Header- Datei einfügen, wenn Sie sie nicht mehr in Ihrer CPP-Datei definieren möchten void myFunc() {};.
Patapoom

Antworten:

301

Dieser Fehler bedeutet oft, dass eine Funktion eine Deklaration, aber keine Definition hat.

Beispiel:

// A.hpp
class A
{
public:
  void myFunc(); // Function declaration
};

// A.cpp

// Function definition
void A::myFunc()
{
  // do stuff
}

In Ihrem Fall kann die Definition nicht gefunden werden. Das Problem könnte sein, dass Sie eine Header-Datei einfügen, die einige Funktionsdeklarationen enthält, aber Sie entweder:

  1. Definieren Sie die Funktionen nicht in Ihrer CPP-Datei (wenn Sie diesen Code selbst geschrieben haben).
  2. Fügen Sie nicht die lib / dll-Datei hinzu, die die Definitionen enthält

Ein häufiger Fehler ist, dass Sie eine Funktion als eigenständig definieren und den Klassenselektor vergessen, z. B. A::in Ihrer .cpp Datei:

Falsch: void myFunc() { /* do stuff */ }
Richtig: void A::myFunc() { /* do stuff */ }

Chris Morris
quelle
2
Wie kann ich die besagte lib-Datei in mein Projekt aufnehmen?
tmj
@tMJ Es hängt davon ab, welche Umgebung Sie verwenden. Ich würde Tutorials online oder auf dieser Website nachschlagen.
Chris Morris
@ChrisMorris Die Definition der Funktion war nicht verfügbar, nicht weil ich sie nicht richtig verknüpft habe oder so. Aber weil die DLL nicht im Speicher war und über einen LoadLibrary-Aufruf geladen werden musste. (FTR)
tmj
2
Der letzte Rat war genau das Problem hier. Ich tat void myFunc() {}statt A::void myFunc() {}.
Charles
Geniale Antwort. Ich hatte tatsächlich sowohl (1) als auch den A :: -Teil vergessen, nachdem ich die Methode von einer anderen Stelle kopiert hatte.
RoG
24

Überprüfen Sie, ob Sie alle Quelldateien in Ihre Lösung aufnehmen, auf die Sie verweisen.

Wenn Sie die Quelldatei (und damit die Implementierung) für die Klasse nicht Fieldin Ihr Projekt aufnehmen, wird sie nicht erstellt und Sie können während der Kompilierung keine Verknüpfung herstellen.

Alternativ verwenden Sie möglicherweise eine statische oder dynamische Bibliothek und haben vergessen, dem Linker das .libs mitzuteilen ?

Konrad
quelle
3
Durch Verweisen auf die richtigen lib-Dateien wurde das Problem behoben. Verwenden Sie Projekt-> Eigenschaften-> Linker-> Allgemein-> Zusätzliche Bibliotheksverzeichnisse und Projekt-> Eigenschaften-> Linker-> Eingabe-> Zusätzliche Abhängigkeiten, um auf das lib-Verzeichnis und die lib-Dateien zu verweisen
zak
11

Es scheint, als ob eine Bibliothek oder ein Include fehlt. Sie können versuchen, herauszufinden, welche Klasse Ihrer Bibliothek getName, getType usw. hat, und diese in die Header-Datei einfügen oder verwenden #include.

Auch wenn diese zufällig aus einer externen Bibliothek stammen, stellen Sie sicher, dass Sie in Ihrer Projektdatei auf sie verweisen. Wenn diese Klasse beispielsweise zu einer abc.lib gehört, dann in Ihrem Visual Studio

  1. Klicken Sie auf Projekteigenschaften.
  2. Gehen Sie zu Konfigurationseigenschaften, C / C ++, Generieren, und vergewissern Sie sich, dass Sie unter Additional Include Directories auf den Speicherort abc.lib verweisen. Stellen Sie unter Linker, Eingabe sicher, dass Sie die abc.lib unter Zusätzliche Abhängigkeiten haben.
Fylix
quelle
9

Ich habe gerade das Problem gesehen, dass ich keine Funktion von main in der CPP-Datei aufrufen kann, die korrekt in der H-Datei deklariert und in der C-Datei definiert ist. Es ist ein Linkerfehler aufgetreten. In der Zwischenzeit kann ich die Funktion aus der üblichen .c-Datei aufrufen. Möglicherweise hängt es von der Anrufkonvention ab. Die Lösung bestand darin, jeder .h-Datei die folgenden Preproc-Zeilen hinzuzufügen:

#ifdef __cplusplus
extern "C"
{
#endif

und diese am Ende

#ifdef __cplusplus
}
#endif
Alexey257
quelle
7

Ich hatte einen Fehler, bei dem mein Projekt als x64- Projekt kompiliert wurde . und ich habe eine Bibliothek verwendet , die als x86 kompiliert wurde .

Ich habe die Bibliothek als x64 neu kompiliert und sie gelöst.

Gal Bracha
quelle
5

Manchmal, wenn eine neue Header-Datei hinzugefügt wird und dieser Fehler aufgrund dessen auftritt, müssen Sie auch eine Bibliothek hinzufügen, um sie zu entfernen unresolved external symbol.

beispielsweise:

#include WtsApi32.h

wird brauchen:

#pragma comment(lib, "Wtsapi32.lib") 
Shashank
quelle
4

Ich hatte die gleichen Linkfehler, aber aus einem Testprojekt, das auf eine andere DLL verwies. Es wurde festgestellt, dass nach dem Hinzufügen _declspec(dllexport)vor jeder Funktion, die in der Fehlermeldung angegeben wurde, der Link gut funktionierte.

meJustAndrew
quelle
3

Ich glaube, die meisten Punkte in Bezug auf die Ursachen und Abhilfemaßnahmen wurden von allen Mitwirkenden in diesem Thread behandelt. Ich möchte nur auf mein 'ungelöstes externes' Problem hinweisen, das durch einen als Makro definierten Datentyp verursacht wurde, der anders als erwartet ersetzt wird, was dazu führt, dass der fraglichen Funktion dieser falsche Typ zugeführt wird, und da die Funktion mit Typ ist nie definiert, es konnte nicht gelöst werden. Insbesondere unter C / C ++ -> Sprache gibt es ein Attribut namens "WChar_t als eingebauten Typ behandeln", das als "Nein (/ Zc: wchar_t-)" hätte definiert werden sollen, in meinem Fall jedoch nicht.

Patrick Nguyen
quelle
danke, dies verursacht das Problem aus meinem Setup ('No (/ Zc: wchar_t-)')
Noypi Gilas
2

Zusätzlich zu der hervorragenden Antwort von Chris Morris oben habe ich eine sehr interessante Möglichkeit gefunden, wie Sie denselben Fehler erhalten können, wenn Sie eine virtuelle Methode aufrufen, die nicht auf rein eingestellt ist, aber keine eigene Implementierung hat. Es ist genau der gleiche Grund (der Compiler kann keine Implementierung der Methode finden und daher Gauner), aber meine IDE hat diesen Fehler nicht im geringsten erkannt.

Der folgende Code würde beispielsweise einen Kompilierungsfehler mit derselben Fehlermeldung erhalten:

//code testing an interface
class test
{
   void myFunc(); 
}

//define an interface
class IamInterface
{
    virtual void myFunc();
}

//implementation of the interface
class IamConcreteImpl
{
    void myFunc()
    {
       1+1=2;
    }
}

Wenn Sie jedoch IamInterface myFunc () in eine rein virtuelle Methode ändern (eine Methode, die "implementiert werden muss", die als "virtuelle Methode" eine Methode ist, die "überschrieben werden kann"), wird der Kompilierungsfehler behoben.

//define an interface
class IamInterface
{
    virtual void myFunc() = 0;
}

Hoffentlich hilft dies der nächsten StackOverFlow-Person, die den Code durchläuft!

GMLewisII
quelle
2

Siehe Linker Tools-Fehler LNK2019 bei MSDN. Dort finden Sie eine detaillierte Liste der häufigsten Probleme, die LNK2019 verursachen.

Alessandro Jacopson
quelle
2

Stellen Sie sicher, dass Sie Ihre Header-Dateien mit dekorieren

#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H

// your header code here

#endif

Schlechte Dinge - einschließlich dieser - können passieren, wenn Sie dies nicht tun

Panouden
quelle
8
Wie wäre es mit #pragma once?
Allen Linatoc
2

Noch ein mögliches Problem (über das ich mich einige Zeit am Kopf gekratzt habe):

Wenn Sie Ihre Funktionen als definieren inline, müssen sie - natürlich! - im Header (oder in einer Inline- Datei) definiert werden, nicht in einem CPP .
In meinem Fall waren sie in einer Inline - Datei, aber nur , weil sie eine plattformspezifische Implementierung waren, und ein CPP enthalten diese entsprechenden inl Datei ... anstelle eines Headers. Ja, das passiert nicht.

Ich dachte, ich würde das auch hier lassen, vielleicht stößt jemand anderes auf dasselbe Problem und findet es hier.

Johann Studanski
quelle
1
An wen auch immer, der dies abgelehnt hat: Hinterlassen Sie mindestens einen Kommentar, warum Sie der Meinung sind, dass die Antwort falsch oder nicht hilfreich ist. Eine Gegenstimme ohne Kommentar ist bestenfalls wertlos.
Johann Studanski
1

Ich hatte es gerade schwer damit. Alles wurde logisch eingerichtet. Ich habe einen Konstruktor deklariert, ihn aber nicht definiert

class SomeClass
{
   SomeClass();  // needs the SomeClass::SomeClass(){} function defined somewhere, even here
}

Ich hätte fast meinen Kopf auf meine Tastatur geschlagen, als ich etwas so Grundlegendes vergessen hatte.

Joe Plante
quelle
1

Ich mache zum ersten Mal seit langer Zeit etwas C ++ und erhalte diesen Fehler, wenn ich vergesse, das Präfix ClassName :: für die Funktionsdefinition hinzuzufügen, da dies ein wenig einzigartig für C ++ ist. Denken Sie also auch daran, dies zu überprüfen!

Matthew Hayes
quelle
1

Eine mögliche Ursache für diesen Linkerfehler können auch inlineFunktionen sein, die deklariert, aber nicht in einer Header-Datei definiert sind, die dann an einer anderen Stelle enthalten ist. Inline-Funktionen müssen in jeder Übersetzungseinheit definiert werden, in der sie verwendet werden.

bweber
quelle
0

Zeiger

Ich hatte dieses Problem und löste es mit einem Zeiger. Ich sehe, dass dies nicht Ihr Problem war, aber ich dachte, ich würde es erwähnen, weil ich mir sicher wünschte, es wäre hier gewesen, als ich es vor einer Stunde gesehen habe. Mein Problem bestand darin, eine statische Elementvariable zu deklarieren, ohne sie zu definieren (die Definition muss nach einigen anderen Setups erfolgen), und natürlich benötigt ein Zeiger keine Definition. Ebenso elementarer Fehler: P.

Rabel
quelle
3
Ein Beispiel wäre hier sehr nützlich.
Moffeltje
0

Mein Problem war, dass in einem Sconscript die cppDatei nicht definiert war. Dies kann sehr verwirrend sein, da Visual Studio die cppDatei im Projekt hat, aber etwas ganz anderes erstellt wird.

ubershmekel
quelle
0

Mein Problem war: Ich musste eine Vorwärtserklärung der Klasse abgeben, deren ctor "ungelöst extern" war.

In die Datei, in der ich den Fehler erhalten habe, musste ich Folgendes einfügen:

#include "ClassB" 

class ClassB; // this solved the problem

class ClassA{
    void foo(){
        ClassB* tmp = new ClassB();
        // ...
    }
};

Natürlich ist mein Projekt viel komplizierter und dies ist nur ein Beispiel. Deklarieren Sie auch Namespaces, wenn Sie diese verwenden .

Vicrucann
quelle
0

Ich habe nur ein paar Stunden damit verbracht herauszufinden, dass das Problem darin bestand, dass meine Hauptdatei eine Erweiterung .canstelle von hatte.cpp

:/

Madhur
quelle
0

Noch eine Möglichkeit zu überprüfen, diesmal war es mein Problem.

Ich hatte die Funktion zur Bibliothek hinzugefügt und den Ausgabeordner der Bibliothek in den Suchpfad aufgenommen.

Ich hatte aber auch einen Ordner mit einer älteren Version der Bibliothek, der zuvor aufgeführt war, sodass VS die alte Bibliothek verwendete und natürlich die neue Funktion nicht fand.

Francesco Dondi
quelle
0

Stellen Sie sicher, dass Sie nicht versuchen, die Einfüge- oder Extraktionsoperatoren als Inline-Funktionen zu überladen. Ich hatte dieses Problem und es ging erst weg, als ich dieses Schlüsselwort entfernte.

Beck
quelle
0

Was hatte es in meinem Fall verursacht:

Ich hatte eine riesige Datei Foo.cppohne Foo.h. Foo.cppbegann so:

// ... 100 LOC here ...
namespace NS {
// ... 100 more LOC here ...
static int var;

Ich habe das Schlüsselwort "static" entfernt und ein Foo.hmit dem folgenden hinzugefügt :

extern int var;

Sehen Sie den Fehler?

Ich habe total vermisst, dass var ursprünglich in einem Namespace definiert wurde, weil die Namespace-Deklaration in anderem Code vergraben war. Die Lösung besteht darin, das Externe wie folgt zu ändern:

namespace NS {
     extern int var;
}
Stefan Monov
quelle
0

Ein möglicher Grund für den Fehler "Nicht gelöstes externes Symbol" kann die Funktionsaufrufkonvention sein.

Stellen Sie sicher, dass alle Quelldateien denselben Standard (.c oder .cpp) verwenden, oder geben Sie die Aufrufkonvention an.

Wenn andernfalls eine Datei eine C-Datei (source.c) und eine andere Datei eine CPP-Datei ist und sie mit demselben Header verknüpft sind, wird der Fehler "ungelöstes externes Symbol" ausgelöst, da die Funktion zuerst als definiert wird Eine C cdecl-Funktion, aber dann sucht eine C ++ - Datei, die denselben Header verwendet, nach einer C ++ - Funktion.

Stellen Sie sicher, dass die Funktionsaufrufkonvention für alle verwendeten Dateien gleich bleibt, um den Fehler "Ungelöster externer Symbolfehler" zu vermeiden.

Flavio
quelle
0

Ich bin hierher gekommen, um nach einer möglichen Erklärung zu suchen, bevor ich mir die Zeilen vor dem Linker-Fehler genauer angesehen habe. Es stellte sich heraus, dass es sich um eine zusätzliche ausführbare Datei handelte, für die die globale Deklaration fehlte!

Jerry Miller
quelle
0

Ich habe gerade den gleichen Fehler hatte und ich schaffe es zu vermeiden , durch den Austausch ;mit {}in der Header - Datei.

#ifndef XYZ_h
#define XYZ_h
class XYZ
{
    public:
    void xyzMethod(){}
}
#endif

Als es war void xyzMethod();, wollte es nicht kompilieren.

Lisedra
quelle