2016-12-14 30 views
5

Próba skompilowania tego cfgparser example.linker nie może znaleźć symboli, ale one tam są?

$ 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 

ale wyraźnie te symbole są tam:

$ 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 

W przeciwieństwie do innych podobnych problemów na tak, to nie chodzi o kolejność łączenie, ponieważ jest tylko jeden plik obiektowy są ze sobą powiązane. Coś, czego mi brakuje?

+1

Zgaduję, że oba moduły są zbudowane w taki sposób, że 'std :: string' oznacza dla nich różne rzeczy. Być może wiąże się to z różnymi wersjami biblioteki uruchomieniowej C++? –

+0

Problem może polegać na tym, że dodajesz 'stdio.h', a nie' cstdio', jeśli skopiowałeś przykładowy kod. To pasuje do zepsutego powiązania w materiałach związanych z char. Inne rzeczy do sprawdzenia: czy twój plik 'libcfgparser.so' został zbudowany z' std :: string' obsługującym 'wchar_t'? – starturtle

+0

Miałem ten sam problem, który zapewni zgodność ABI, upewniając się, że -m32/-m64 pasuje do twojej biblioteki/plików wykonywalnych. – ceorron

Odpowiedz

11

ale wyraźnie te symbole są tam:

Oczywiście, że nie. Przyjrzyj się bliżej, a zobaczysz, że nie ma dopasowań między sygnaturami zgłoszonymi przez linker jako niezdefiniowanymi i tymi zgłoszonymi z biblioteki przez nm.

Nagłówek Standardowy <string> definiuje std::string jako typedef dla:

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

Realizacja GCC z <string>, począwszy od cxx11 ABI (gcc 4.7.0) definiuje std::string jako typedef dla:

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

Przestrzeń nazw std::__cxx11 zawiera typy, których implementacje binarne są zgodne z cxx1: 1 ABI.

Definicja rodzaju oznacza, że ​​C++, JT, które zawiera standardowy nagłówek <string> nie będzie kompilacji GCC> = 4,7, do kodu wynikowego zawierającym symbol, który demangles jak std::string.

Jeżeli binarny - jak twój libcfgparser.so - zawiera symbol, który demangles jak std::string, następnie cokolwiek to symbol mogło, o którym mowa w źródłach, z którego został zbudowany, to nie odnosi się dostd::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, i nie może być połączone z innymi plikami binarnymi, które zostały skompilowane z tą definicją std::string.

Twój libcfgparser.so jest jeden zainstalowany przez libcfgparser0_1.1.2_amd64.deb z cfgparser Sourceforce project (który był ostatnio aktualizowany trzy lata temu). Domyślam się, że fakt, że I dostać twój błąd połączenia z tym samym example.cc program połączony z biblioteką, która jest zainstalowana przez ten pakiet.

Wyjaśnienie błędu objawia się przez:

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

który mówi nam, że ta biblioteka została zbudowana z GCC 4.3.2 - Pre cxx11 ABI.

The std::string który pojawia się w swoim wyjściu nm jest pre-cxx11 demangling skrót z std::basic_string<char, std::char_traits<char>, std::allocator<char>>.

Ten libcfgparser.so jest niekompatybilny z ABI z bieżącym GCC, więc użytkownik nie może połączyć go z programami budowanymi przy użyciu tego kompilatora. Co można zrobić, to zbudować libcfgparser z pakietu źródłowego, libcfgparser-1.1.2.tar.bz2, z bieżącym kompilatorem, a następnie połączyć swoje programy z biblioteką, którą sam zbudowałeś.

To działa, ale nie bez wysiłku. Najpierw musisz naprawić zepsutą wersję i przestarzałe automatyczne ustawianie pakietu źródłowego, aby utworzyć działający skrypt.

Co nie daje pocieszającego wrażenia na sprawność opiekuna pakietu. Plus kod źródłowy pakietu, copyright 2008, jest amatorskiej jakości. Jeśli to, czego szukasz, to parser C++ dla plików w stylu INI, to boost::property_tree::ini_parser będzie rozwiązaniem goto . Zobacz this answer

+0

Dzięki! Twoja odpowiedź jest bardzo pomocna i edukacyjna. Zgaduję, że z podobnego powodu, ale nie mogę dojść do wniosku, ponieważ "The' std :: string', który pojawia się w wyjściowym 'nm' jest pre-cxx11 demangling ** skrót ** z' std :: basic_string , std :: allocator > '- Nie wiem jak poprawnie skreślić' std :: string' . – qweruiop

+0

Również użycie 'boost :: property_tree :: ini_parser' jest dobrym połączeniem – qweruiop

+0

@qweruiop Nie ma za co. 'std :: string' (demangled) =' Ss' (zmanipulowany) był * sztywnym * skrótem w myllingowaniu GCC pre-cxx11.Nie logika do niego, ale wygoda. Można liczyć, że symbole w plikach binarnych, niezależnie od tego, czy są zniekształcone czy zniekształcone, które * są * inne * są inne niż linker *, ponieważ są tym, co widzi łącznik. –

Powiązane problemy