Konvertieren von std :: __ cxx11 :: string in std :: string

73

Ich verwende c ++ 11, aber auch einige Bibliotheken, die nicht dafür konfiguriert sind und eine Typkonvertierung benötigen. Insbesondere brauche ich einen Weg, um std::__cxx11::stringauf regulär std::stringumzusteigen, aber googeln kann ich nicht finden, und dies (string)funktioniert nicht.

Wenn ich nicht konvertiere, erhalte ich folgende Linker-Fehler:

undefined reference to `H5::CompType::insertMember(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, H5::DataType const&) const'
jorgen
quelle
1
Der Fehler klingt eher so, als ob der Compiler die insertMember()Methode nicht finden kann.
Matthäus Brandl
1
Hm, es kann es mit anderen Programmen finden, die ich habe, die nicht verwendenc++11
jorgen
1
Außerdem verwenden Sie vermutlich gcc. Ich würde erwarten, dass sich typedef __cxx11::basic_string basic_stringirgendwo im stdNamespace des String-Headers etwas befindet. Kompilieren Sie auch die Kompilierungseinheit H5::CompType?
Matthäus Brandl
4
"Ich verwende c ++ 11, aber auch einige Bibliotheken, die nicht dafür konfiguriert sind". Diese Situation ist problematisch und man kann nicht wirklich erwarten, dass etwas funktioniert. gcc.gnu.org/wiki/Cxx11AbiCompatibility web.archive.org/web/20170210052503/http://… und so weiter.
n. 'Pronomen' m.
3
Ich mich auf diese Frage nach der Fehlerbehebung gefunden, so dass ich dachte , ich würde Aktie war das Problem , dass ich mit , gccanstatt g++zu kompilieren ...
Aaron Franke

Antworten:

105

Ist es möglich, dass Sie GCC 5 verwenden?

Wenn Sie Linkerfehler über undefinierte Verweise auf Symbole erhalten, die Typen im Namespace std :: __ cxx11 oder im Tag [abi: cxx11] enthalten, weist dies wahrscheinlich darauf hin, dass Sie versuchen, Objektdateien zu verknüpfen, die mit unterschiedlichen Werten für _GLIBCXX_USE_CXX11_ABI kompiliert wurden Makro. Dies ist häufig der Fall, wenn eine Verknüpfung zu einer Drittanbieter-Bibliothek hergestellt wird, die mit einer älteren Version von GCC kompiliert wurde. Wenn die Bibliothek eines Drittanbieters mit dem neuen ABI nicht wiederhergestellt werden kann, müssen Sie Ihren Code mit dem alten ABI neu kompilieren.

Quelle: GCC 5 Release Notes / Dual ABI

Das Definieren des folgenden Makros vor dem Einfügen von Standardbibliotheksheadern sollte Ihr Problem beheben:#define _GLIBCXX_USE_CXX11_ABI 0

Matthäus Brandl
quelle
4
Ich habe es versucht; Jetzt bekomme ich überall Linkerfehler, wenn ich C ++ 11-Funktionen verwende. Vielleicht gibt es keine Möglichkeit, dies sowohl mit c ++ 11 als auch mit der kompilierten hdf5-Bibliothek zum Laufen zu bringen.
Jorgen
1
Unter Ubuntu 14.04 wird g ++ 6.2 standardmäßig mit diesem Wert auf 0 kompiliert, während unter 16.04 dieselbe g ++ - Version mit dem Wert 1 kompiliert wird. Unter 14.04 scheint das Setzen von 1 auf 1 eigentlich nichts zu bewirken. Die resultierende Objektdatei verwendet nicht den CXX11 ABI. Ich vermute, dass dies eine Systembeschränkung ist.
Devin Lane
Ich war mir nicht sicher, warum der Compiler wirft, undefined referenceund bevor ich nach einer Lösung suchte, überprüfte ich meine gesamte Verknüpfung im Programm und fand nichts. Danach entschied ich mich, im Web zu suchen und fand dies. Es funktioniert wie Charme, danke :)
Shravan40
Vielen Dank, ein Billiardenfacher Mann! Sie haben mich vor einem Debugging-Albtraum gerettet, der mehr als 20 Stunden gedauert hat! Gott segne dich!
Rika
53

Wenn Sie alle inkompatiblen Bibliotheken, die Sie verwenden, neu kompilieren können, tun Sie dies mit der Compiler-Option

-D_GLIBCXX_USE_CXX11_ABI = 1

und erstellen Sie dann Ihr Projekt neu. Wenn Sie dies nicht tun können, fügen Sie die Makefile-Compiler-Option Ihres Projekts hinzu

-D_GLIBCXX_USE_CXX11_ABI = 0

Die definieren

#define _GLIBCXX_USE_CXX11_ABI 0/1

ist auch gut, aber Sie müssen es wahrscheinlich zu allen Ihren Dateien hinzufügen, während die Compiler-Option dies für alle Dateien gleichzeitig tut.

Denis Sirotkin
quelle
3
Das Compiler-Flag hat bei mir funktioniert. Vielen Dank. Ich habe 4 Tage für diese dumme Änderung in gcc verschwendet!
Behrouz.M
5

Wenn ich ein ähnliches Problem hatte, ist es passiert, weil meine Bibliothek mit erstellt clang++wurde und libstdc++.soauf meinem System standardmäßig mit verknüpft ist. Während App-Binärdatei clangmit -lc++Option erstellt und mit Option verknüpft wurde .

Der einfachste Weg, Abhängigkeiten zu überprüfen, ist die Durchführung ldd libName.so

Um dies zu beheben, sollten Sie dieselbe Bibliothek in App und Bibliothek verwenden.

  • Einfachster Weg. Erstellen Sie eine Bibliothek mit clang++und kompilieren Sie eine App mit clang++. Ohne zusätzliche Verknüpfungsoptionen für beide Schritte. Standardmäßig wird stdlib verwendet.

  • Bibliothek -stdlib=c++erstellen mit und App kompilieren mit -lc++. In diesem Fall werden sowohl die Bibliothek als auch die App verwendet libc++.so.

  • Erstellen Sie eine Bibliothek ohne zusätzliche Optionen und verknüpfen Sie die Binärdatei mit -lstdc++. In diesem Fall werden sowohl die Bibliothek als auch die App verwendet libstdc++.so.

Evgen Bodunov
quelle
3

Die Antworten hier konzentrieren sich hauptsächlich auf kurze Wege, um das Problem zu beheben. Wenn dies jedoch nicht hilft, gebe ich einige Schritte zur Überprüfung an, die mir geholfen haben (nur Linux):

  • Wenn die Linkerfehler beim Verknüpfen anderer Bibliotheken auftreten, erstellen Sie diese Bibliotheken mit Debug-Symbolen (GCC-Flag "-g").
  • Listen Sie die Symbole in der Bibliothek auf und suchen Sie die Symbole, über die sich der Linker beschwert (geben Sie die Befehle in die Befehlszeile ein):

    nm lib_your_problem_library.a | grep functionNameLinkerComplainsAbout

  • Wenn Sie die Methodensignatur erhalten haben, fahren Sie mit dem nächsten Schritt fort. Wenn Sie no symbolsstattdessen die Signatur erhalten haben, haben Sie höchstwahrscheinlich alle Symbole aus der Bibliothek entfernt. Deshalb kann der Linker sie beim Verknüpfen der Bibliothek nicht finden. Erstellen Sie die Bibliothek neu, ohne ALLE Symbole zu entfernen strip -S. Bei Bedarf können Sie Debug- Symbole ( Optionssymbole) entfernen.

  • Verwenden Sie einen C ++ - Demangler, um die Methodensignatur zu verstehen, z. B. diese

  • Vergleichen Sie die Methodensignatur in der Bibliothek, die Sie gerade erhalten haben, mit der Signatur, die Sie im Code verwenden (überprüfen Sie auch die Header-Datei). Wenn sie unterschiedlich ist, verwenden Sie den richtigen Header oder die richtige Bibliothek oder eine andere Methode, die Sie jetzt kennen, um sie zu beheben
sofort717
quelle
0

Ich habe dies erhalten. Die einzige Möglichkeit, dies zu beheben, bestand darin, das gesamte mingw-64 zu aktualisieren (ich habe dies zu Ihrer Information mit pacman auf msys2 durchgeführt).

Ceorron
quelle
0

Für mich hat -D_GLIBCXX_USE_CXX11_ABI = 0 nicht geholfen.

Es funktioniert, nachdem ich mit C ++ libs Version anstelle von gnustl verlinkt habe.

dimon4eg
quelle
0

Ich hatte kürzlich ein ähnliches Problem, als ich versuchte, eine Verbindung zu den vorgefertigten Binärdateien von hdf5 Version 1.10.5 unter Ubuntu 16.04 herzustellen . Keine der hier vorgeschlagenen Lösungen funktionierte für mich und ich verwendete g ++ Version 9.1. Ich fand, dass die beste Lösung darin besteht, die hdf5-Bibliothek aus dem Quellcode zu erstellen. Verwenden Sie nicht die vorgefertigten Binärdateien, da diese mit gcc 4.9 erstellt wurden! Laden Sie stattdessen die Quellcodearchive von der HDF- Website für Ihre spezielle Distribution herunter und erstellen Sie die Bibliothek. Es ist sehr leicht.

Sie benötigen auch die Komprimierungsbibliotheken zlib und szip von hier bzw. hier , wenn Sie sie noch nicht auf Ihrem System haben.

ungebunden37
quelle
0

In meinem Fall hatte ich ein ähnliches Problem:

/usr/bin/ld: Bank.cpp:(.text+0x19c): undefined reference to 'Account::SetBank(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)' collect2: error: ld returned 1 exit status

Nach einigen Recherchen stellte ich fest, dass das Problem durch die Art und Weise verursacht wurde, wie Visual Studio Code die Datei Bank.cpp kompilierte. Um dies zu lösen, habe ich nur den Befehl follow aufgerufen, um die erfolgreiche C ++ - Datei zu kompilieren:

g++ Bank.cpp Account.cpp -o Bank

Mit dem obigen Befehl konnte es die Header-, Implementierungs- und Main-C ++ - Dateien korrekt verknüpfen.

OBS: Meine g ++ Version: 9.3.0 unter Ubuntu 20.04

Tiago Sá
quelle