Frage

Ich lief nur über die folgenden Fehler (und die Lösung online zu finden, aber es ist nicht in Stack-Überlauf):

  

(gnu.linkonce [Sachen]..): Undefined   Bezugnahme auf [Methode] [object   file] :( gnu.linkonce [Sachen])..:   undefined reference to `Typeinfo für   [Classname]

Warum man eine dieser bekommen könnte Linkerfehler "undefined reference to Typeinfo"?

(Bonuspunkte, wenn Sie erklären, was hinter den Kulissen passiert.)

War es hilfreich?

Lösung

Ein möglicher Grund ist, weil Sie eine virtuelle Funktion deklarieren, ohne sie zu definieren.

Wenn Sie es erklären, ohne sie in derselben Übersetzungseinheit definiert, die Sie darauf hinweisen, dass es irgendwo anders definiert ist - das bedeutet, die Linker Phase werden versuchen, die anderen Übersetzungseinheiten in einer finden (oder Bibliotheken)

Ein Beispiel die virtuelle Funktion zu definieren ist:

virtual void fn() { /* insert code here */ }

In diesem Fall Sie eine Definition der Erklärung angebracht, was bedeutet, der Linker nicht später muss es lösen.

Die Zeile

virtual void fn();

erklärt fn(), ohne es zu definieren, und bewirkt, dass die Fehlermeldung Sie gefragt.

Es ist sehr ähnlich den Code:

extern int i;
int *pi = &i;

, die besagen, dass die ganze Zahl i in einer anderen Übersetzungseinheit deklariert wird, die zur Verknüpfungszeit gelöst werden muss (sonst pi kann nicht eingestellt werden, um es Adresse ist).

Andere Tipps

Dies kann auch passieren, wenn Sie -fno-rtti und -frtti Code mischen. Dann müssen Sie sicherstellen, dass jede Klasse, die type_info im -frtti Code zugegriffen wird, hat ihr Key-Verfahren mit -frtti zusammengestellt. Ein solcher Zugang kann passieren, wenn Sie ein Objekt der Klasse erstellen, verwenden dynamic_cast etc.

[ Quelle ]

Dies geschieht, wenn deklariert (nicht rein) virtuelle Funktionen fehlen Körper. In Ihrer Klassendefinition, so etwas wie:

virtual void foo();

Sollte (inline oder in einer verknüpften Quelldatei) definiert werden:

virtual void foo() {}

oder erklärt rein virtuelle:

virtual void foo() = 0;

Zitiert von dem gcc Handbuch :

  

Für polymorphe Klassen (Klassen mit virtuellen Funktionen) wird das type_info Objekt zusammen mit der V-Tabelle geschrieben [...] Für alle anderen Typen, schreiben wir das type_info Objekt, wenn es verwendet wird: bei der Anwendung `typeid‘ zu ein Ausdruck, ein Objekt zu werfen, oder sich auf eine Art in einer catch-Klausel oder Ausnahme-Spezifikation.

Und ein bisschen früher auf der gleichen Seite:

  

Wenn die Klasse deklariert alle nicht inline, nicht-reine virtuelle Funktionen, die ersten, wird als das „Key-Verfahren“ für die Klasse gewählt und die vtable ist nur in der Übersetzungseinheit ausgesendet, wo das Key-Verfahren definiert ist.

Also, dieser Fehler tritt auf, wenn das „Key-Verfahren“ ihre Definition fehlt, wie andere Antworten bereits erwähnt.

Wenn Sie eine .so zum anderen sind die Verknüpfung, noch eine weitere Möglichkeit, kompiliert mit „-fvisibility = versteckt“ in gcc oder g ++. Wenn beide .so-Dateien mit „-fvisibility = hidden“ und der Key-Verfahren gebaut wurden als eine andere der virtuellen Funktion der Implementierungen nicht in der gleichen .so ist, sehen diese nicht die V-Tabelle oder Typeinfo der ersteren. An dem Linker, das sieht aus wie eine nicht implementierte virtuelle Funktion (wie in paxdiablo die und cdleary die Antworten).

In diesem Fall müssen Sie eine Ausnahme für die Sichtbarkeit der Basisklasse mit

machen
__attribute__ ((visibility("default")))

in der Klassendeklaration. Zum Beispiel

class __attribute__ ((visibility("default"))) boom{
    virtual void stick();
}

Eine andere Lösung, natürlich, ist nicht zu verwenden „-fvisibility = versteckt.“ Das verkompliziert die Dinge für den Compiler und Linker, möglicherweise zu Lasten der Code Leistung.

Die bisherigen Antworten sind richtig, aber dieser Fehler kann auch durch den Versuch, auf einem Objekt einer Klasse zu verwenden typeid verursacht wird, hat keine virtuelle Funktionen. C ++ RTTI erfordert eine V-Tabelle, so Klassen, die Sie wünschen Typerkennung durchzuführen auf mindestens eine Funktion virtueller erfordern.

Wenn Sie Informationen wünschen geben für eine Klasse zu arbeiten, für die Sie wirklich keine virtuellen Funktionen möchten, stellen Sie das Destruktor virtuell.

Mögliche Lösungen für Code, der mit RTTI und Nicht-RTTI-Bibliotheken beschäftigen:

a) Recompile alles entweder mit -frtti oder -fno-rtti
b) Wenn a) für Sie nicht möglich ist, versuchen Sie Folgendes:

Angenommen libfoo ohne RTTI gebaut. Ihr Code verwendet libfoo und kompiliert mit RTTI. Wenn Sie eine Klasse (Foo) in libfoo verwenden, die virtuals hat, sind Sie wahrscheinlich in einen Link Zeitfehler auszuführen, die sagt: fehlende Typeinfo für die Klasse Foo

.

Definieren Sie eine andere Klasse (z FooAdapter), die keine virtuellen hat und Anrufe weiterleiten Foo, dass Sie verwenden.

Compile FooAdapter in einer kleinen statischen Bibliothek, die nicht RTTI nicht verwendet und hängt nur von libfoo Symbolen. Geben Sie einen Header für sie und verwenden, die stattdessen in Ihrem Code (die RTTI verwendet). Da FooAdapter keine virtuelle Funktion hat, wird es keine Typeinfo haben, und Sie werden in der Lage sein, die Binärdatei zu verknüpfen. Wenn Sie eine Menge verschiedener Klassen von libfoo verwenden, kann diese Lösung nicht bequem sein, aber es ist ein Anfang.

Ich habe gerade ein paar Stunden auf diesem Fehler, und während der anderen Antworten hier haben mir geholfen, zu verstehen, was los war, haben sie nicht mein besonderes Problem zu beheben.

ich an einem Projekt arbeite, die sowohl mit clang++ und g++ kompiliert. Ich habe keine Verknüpfung Probleme clang++ mit, wurde aber immer die undefined reference to 'typeinfo for Fehler mit g++.

Der wichtige Punkt: Verknüpfung, um MATTERS mit g++. Wenn Sie die Bibliotheken aufzulisten, die Sie in einem Auftrag verknüpfen möchten, die falsch ist, dass Sie die typeinfo Fehler erhalten können.

Siehe diese SO, um weitere Informationen über die Verknüpfung, um mit gcc / g++ Frage .

Ähnlich wie bei der RTTI, NO-RTTI Diskussion über, kann dieses Problem auch auftreten, wenn Sie dynamic_cast verwenden und nicht den Objektcode enthält die Klassenimplementierung gehören.

Ich lief in dieses Problem Gebäude auf Cygwin und dann auf Linux portieren Code. Die Make-Dateien, die Verzeichnisstruktur und auch die gcc-Versionen (4.8.2) waren in beiden Fällen identisch, aber der Code verknüpft und korrekt auf Cygwin betrieben aber nicht auf Linux zu verknüpfen. Red Hat Cygwin hat offenbar Compiler / Linker Modifikationen vorgenommen, die den Objektcode Verknüpfung Anforderung zu vermeiden.

Der Fehler Linux Linker-Nachricht richtet mich richtig an die dynamic_cast Linie, aber früher Nachrichten in diesem Forum hatte mich auf der Suche nach Funktion Implementierungen fehlt nicht das eigentliche Problem: fehlende Objektcode. Meine Abhilfe war eine virtuelle Funktion des Typs in der Basis und abgeleitete Klasse zu substituieren, z.B. virtual int isSpecialType (), anstatt Verwendung dynamic_cast. Diese Technik vermeidet die Anforderung Objekt Implementierungscode zu verknüpfen nur dynamic_cast zu bekommen richtig zu arbeiten.

In der Basisklasse (eine abstrakte Basisklasse) Sie einen virtuellen Destruktor deklarieren und wie Sie keine destructor als rein virtuelle Funktion erklären kann, entweder haben Sie es zu definieren, hier in der abstrakten Klasse, nur eine Dummy-Definition wie virtuelle ~ base () {} tun wird, oder in einem der abgeleiteten Klasse.

Wenn Sie dies nicht tun, werden Sie in einem „undefinierten Symbol“ am Ende zur Verknüpfungszeit. Da VMT einen Eintrag für alle rein virtuelle Funktionen mit einem passenden NULL hat, wie es in der Tabelle auf der Umsetzung in der abgeleiteten Klasse abhängig aktualisiert. Aber für die nicht rein, sondern virtuelle Funktionen, es die Definition auf dem Link Zeit braucht, so dass es die VMT-Tabelle zu aktualisieren.

Verwenden c ++ filt das Symbol demangle. Wie $ c ++ filt _ZTIN10storageapi8BaseHostE ausgibt so etwas wie "Typeinfo für storageapi :: BaseHost".

Ich habe eine Menge von diesen eben Fehler. Was passiert ist, dass ich eine Header-Datei-only-Klasse in eine Header-Datei und eine CPP-Datei aufgeteilt. Allerdings habe ich nicht meine Build-System aktualisieren, so dass die CPP-Datei nicht kompiliert bekommen haben. Unter einfach undefinierten Referenzen auf die Funktionen, die im Header deklariert, aber nicht umgesetzt, habe ich eine Menge von diesem Fehler Typeinfo.

Die Lösung wurde erneut ausführt das Build-System zu kompilieren und die neue CPP-Datei zu verknüpfen.

in meinem Fall habe ich eine Drittanbieter-Bibliothek mit Header-Dateien und so Datei. i subclassed eine Klasse, und Verbindungsfehler wie dies aufgetreten ist, wenn ich versuche, meine Unterklasse zu instanziiert.

, wie durch @sergiy erwähnt, knowning es könnte das Problem der ‚rtti‘ sein, habe ich es geschafft umgehen, indem Sie setzen den Konstruktor Implementierung in separate CPP-Datei und wenden ‚-fno-rtti‘ kompilieren Fahnen der Datei . es funktioniert gut.

, wie ich bin immer noch nicht ganz klar über die internen diesen Link-Fehler, sie ist nicht sicher, ob meine Lösung allgemein. aber ich denke, es einen Versuch wert, bevor Sie den Adapter Art und Weise versucht, wie von @francois erwähnt. und natürlich, wenn alle Quelltexte verfügbar sind (nicht in meinem Fall), besser noch neu kompiliert mit ‚-frtti‘, wenn möglich.

eine weitere Sache, wenn Sie meine Lösung, um zu versuchen, versuchen, die separate Datei so einfach wie möglich machen, und nicht einige ausgefallenen Features von C ++ verwenden. nehmen besondere Aufmerksamkeit auf Schub bezogene Dinge, verursachen viel davon auf rtti abhängt.

Ich habe denselben Fehler, wenn meine Schnittstelle (mit allen reinen virtuellen Funktionen) eine weitere Funktion benötigt und ich habe vergessen zu „null“ es.

Ich hatte

class ICommProvider { public: /** * @brief If connection is established, it sends the message into the server. * @param[in] msg - message to be send * @return 0 if success, error otherwise */ virtual int vaSend(const std::string &msg) = 0; /** * @brief If connection is established, it is waiting will server response back. * @param[out] msg is the message received from server * @return 0 if success, error otherwise */ virtual int vaReceive(std::string &msg) = 0; virtual int vaSendRaw(const char *buff, int bufflen) = 0; virtual int vaReceiveRaw(char *buff, int bufflen) = 0; /** * @bief Closes current connection (if needed) after serving * @return 0 if success, error otherwise */ virtual int vaClose(); };

Zuletzt vaClose ist nicht virtuell so zusammengestellt wusste nicht, wo für sie die Umsetzung zu bekommen und dadurch bekam verwirrt. meine Botschaft war:

  .

... TCPClient.o :( Rodata + 0x38): undefined reference to `Typeinfo für ICommProvider '

Einfacher Wechsel von

virtual int vaClose();

virtual int vaClose() = 0;

das Problem behoben. hoffe, es hilft

Ich begegne eine Situation, die selten ist, aber dies kann andere Freunden in ähnlicher Situation helfen. Ich habe 4.4.7 auf einem älteren System mit gcc zu arbeiten. Ich muss Code mit c ++ kompilieren 11 oder höher unterstützt, so baue ich die neueste Version von gcc 5.3.0. Wenn mein Code den Aufbau und die Anbindung an die Abhängigkeiten, wenn die Abhängigkeit mit älteren Compiler bauen, dann habe ich ‚undefined Verweis auf‘ Fehler, obwohl ich deutlich den Verbindungsweg mit -L / Pfad definiert / to / lib -llibname. Einige Pakete wie Boost und Projekte bauen mit cmake in der Regel eine Tendenz hat, den älteren Compiler zu verwenden und sie in der Regel solche Probleme verursachen. Sie haben einen langen Weg zu gehen, dass sie die neueren Compiler verwenden zu machen.

In meinem Fall ist es eine reine Bibliothek Abhängigkeitsproblem, auch wenn ich dynamic_cast Ruf haben. Nach der Zugabe wurde genug Abhängigkeit in Make-Datei dieses Problem weg.

Überprüfen Sie, ob Ihre Abhängigkeiten ohne -f-nortti zusammengestellt wurden.

Für einige Projekte, die Sie haben es explizit zu setzen, wie in RocksDB:

USE_RTTI=1 make shared_lib -j4
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top