2016-12-14 5 views
5

Versuchen, diese cfgparser example zu kompilieren.Linker kann keine Symbole finden, aber sie sind da?

$ g++ example.cc -lcfgparser 
: In function `main': 
example.cc:(.text+0x6b): undefined reference to `ConfigParser_t::readFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' 
example.cc:(.text+0x160): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0x2d9): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int*) const' 
example.cc:(.text+0x43c): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double*) const' 
example.cc:(.text+0x5b1): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool*) const' 
example.cc:(.text+0x78c): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*) const' 
example.cc:(.text+0xa15): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0xba2): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0xd15): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0xe7f): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
collect2: error: ld returned 1 exit statu 

Aber klar diese Symbole sind:

$ nm -gC /usr/lib/libcfgparser.so 
000000000003710 T ConfigParser_t::readFile(std::string const&) 
0000000000004880 T ConfigParser_t::ConfigParser_t(std::string const&) 
00000000000024c0 T ConfigParser_t::ConfigParser_t() 
0000000000004ad0 T ConfigParser_t::ConfigParser_t(std::string const&) 
00000000000024a0 T ConfigParser_t::ConfigParser_t() 
0000000000004d20 T ConfigParser_t::getOptions(std::string const&) const 
00000000000028d0 T ConfigParser_t::getSections() const 
0000000000002ff0 T ConfigParser_t::getValue(std::string, std::string, bool*) const 
0000000000002de0 T ConfigParser_t::getValue(std::string, std::string, double*) const 
0000000000002bd0 T ConfigParser_t::getValue(std::string, std::string, int*) const 
00000000000027d0 T ConfigParser_t::getValue(std::string, std::string, std::string*) const 
0000000000003500 T ConfigParser_t::getValue(std::string, std::string, std::vector<std::string, std::allocator<std::string> >*) const 

Im Gegensatz zu anderen ähnlichen Problemen auf SO, dann ist dies nicht, um über die Verknüpfung, da es nur eine Objektdatei ist verbunden ist. Alles, was ich vermisse?

+1

Meine Vermutung ist, dass die beiden Module so gebaut sind, dass 'std :: string' verschiedene Dinge für sie bedeutet. Vielleicht mit verschiedenen Varianten der C++ - Laufzeitbibliothek verknüpft? –

+0

Das Problem kann sein, dass Sie "stdio.h" und nicht "cstdio" einschließen, wenn Sie den Beispielcode kopiert haben. Das würde eine defekte Verknüpfung bei Char-bezogenem Zeug entsprechen. Andere zu überprüfende Dinge: Wurde Ihr 'libcfgparser.so' mit' std :: string' erstellt, der 'wchar_t' unterstützt? – starturtle

+0

Ich hatte das gleiche Problem, stellen Sie sicher für ABI-Kompatibilität sicherzustellen, dass die -m32/-m64-Übereinstimmungen für Sie Bibliothek/ausführbare Datei erstellt. – ceorron

Antwort

11

Aber klar diese Symbole sind:

Offensichtlich sind sie nicht. Schauen Sie genauer hin, und Sie werden sehen, dass keine Übereinstimmungen zwischen den Signaturen, die von Ihrem -Linker als undefiniert gemeldet werden, und den von der Bibliothek gemeldeten Signaturen von nm vorliegen.

Die Standard-Header definiert <string>std::string als typedef für:

std::basic_string<char, std::char_traits<char>, std::allocator<char>> 

Die GCC Umsetzung <string>, wie die cxx11 ABI (GCC 4.7.0) std::string definiert als typedef für:

std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> 

Der Namensraum std::__cxx11 umfasst Typen, deren binäre Implementierungen konform mit dem cxx1 sind 1 ABI.

Die Typdefinition bedeutet, dass C++ Übersetzungseinheit, die die Standard-Header werden nicht <string> Kompilierung mit GCC> = 4,7, in dem Objektcode enthält, ein Symbol enthält, das als std::string demangles.

Wenn ein binäres - wie Ihr libcfgparser.so - ein Symbol enthält die als std::string demangles, dann was auch immer das Symbol könnte in den Quellen bezogen haben, aus dem es gebaut wurde, es bezieht sich nicht aufstd::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, und kann nicht mit anderen Binärdateien verknüpft sein, die mit dieser Definition von std::string kompiliert wurden.

Ihre libcfgparser.so ist die von libcfgparser0_1.1.2_amd64.deb vom cfgparser Sourceforce project installiert (die vor drei Jahren zuletzt aktualisiert wurde). Ich schätze das von der Tatsache, dass ich Ihren Verbindungsfehler mit demselben example.cc Programm erhält, das gegen die Bibliothek verbunden wird, die durch dieses Paket installiert wird.

Die Erklärung für den Fehler wird durch offenbart:

/usr/lib$ strings -a libcfgparser.so | grep "GCC: (" 
GCC: (Debian 4.3.2-1.1) 4.3.2 
... 

, die uns sagt, dass diese Bibliothek mit GCC 4.3.2 gebaut wurde - das cxx11 ABI vor.

Die std::string, die in Ihrer nm Ausgabe erscheint, ist ein Pre-cxx11 Abkürzung Demangling von std::basic_string<char, std::char_traits<char>, std::allocator<char>>.

Diese libcfgparser.so ist ABI-inkompatibel mit Ihrem aktuellen GCC, so dass Sie nicht mit Programmen verknüpfen können, die Sie mit diesem Compiler erstellen. Was Sie tun können, ist Build libcfgparser aus dem Quellpaket, libcfgparser-1.1.2.tar.bz2, mit Ihrem aktuellen Compiler und verknüpfen Sie dann Ihre Programme mit der Bibliothek, die Sie gebaut haben.

Das funktioniert, aber nicht mühelos. Zuerst müssen Sie das defekte und antiquierte Autotooling des Quellpakets reparieren, um ein funktionierendes ./configure Skript zu erstellen.

Was keinen beruhigenden Eindruck von der Leistungsfähigkeit des Paketbetreuers gibt. Plus der Quellcode des Pakets, Copyright 2008, ist von Amateurqualität. Wenn was Sie suchen, ist ein C++ Parser für INI-Style-Dateien, dann boost::property_tree::ini_parser wäre die goto Lösung. Siehe this answer

+0

Danke! Ihre Antwort ist sehr hilfreich und lehrreich. Ich habe den ähnlichen Grund vermutet, aber ich kann nicht schließen, wahrscheinlich weil "Die' std :: string', die in deiner 'nm'-Ausgabe erscheint, ist eine vor-cxx11 rückgängig machende ** Abkürzung von 'std :: basic_string , std :: allocator > '- Ich kann' std :: string' nicht richtig abkürzen – qweruiop

+0

Auch die Verwendung von 'boost :: property_tree :: ini_parser' ist ein guter Ruf. – qweruiop

+0

@qweruiop Gern geschehen, die 'std :: string' (entmagnetisiert) =' Ss' (mangled) war eine * hardcoded * Abkürzung im pre-cxx11 GCC name-mangling.Keine Logik, aber Bequemlichkeit kann darauf zählen, dass Symbole innerhalb von Binärdateien, ob verfälscht oder entfremdet, * die * anders sind * als der Linker * sind, weil sie das sind, was der Linker sieht. –

Verwandte Themen