Linker cannot find characters, but are they?

Trying to compile this cfgparser example .

$ 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 

But obviously these characters are:

 $ 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 

Unlike other similar problems on SO, this is NOT about order binding, as there is only one related object file. Anything I miss?

+5
source share
1 answer

But obviously these characters are:

Clearly, this is not so. Come closer and you will see that there are no matches between signatures, linker as undefined, and those that are reported from the library, nm .

The standard <string> header defines std::string as a typedef for:

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

An implementation of GCC <string> , as cxx11 ABI (GCC 4.7.0) defines std::string as a typedef for:

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

The std::__cxx11 specifies types whose binary implementations are compatible with cxx11 ABI.

The definition of this type means that the C ++ translation block, which includes the standard <string> header, will not compile with GCC> = 4.7 into object code containing a character that will be expanded as std::string .

If a binary code similar to your libcfgparser.so contains a character that displays as std::string , then regardless of what that character might have mentioned in the sources it was built from, it does not apply to std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> , and cannot be associated with other binaries that were compiled with this std::string definition.

Your libcfgparser.so is the one installed by libcfgparser0_1.1.2_amd64.deb from the cfgparser Sourceforce project (which was updated three years ago). I think from this fact that I will get my binding error with the same example.cc program associated with the library installed by this package.

An explanation of the error is revealed:

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

which tells us that this library was built using GCC 4.3.2 - prior to cxx11 ABI.

std::string that appears on your nm output is the abbreviation for pre-cxx11 unmarking std::basic_string<char, std::char_traits<char>, std::allocator<char>> .

This libcfgparser.so is ABI incompatible with your current GCC, so you cannot associate it with the programs you create using this compiler. What you can do is build libcfgparser from the source package, libcfgparser-1.1.2.tar.bz2 , with your current compiler, and then link your programs to the library that you have built yourself.

It works, but not without effort. First you need to fix the broken and outdated auto-cooling of the source package to create a working ./configure script.

This does not give an encouraging impression of the professionalism of the accompanying package. Plus, the source code of the package, copyright 2008, has amateur quality. If what you need is a C ++ parser for INI style files, then boost::property_tree::ini_parser will be the goto solution. See this answer

+11
source

Source: https://habr.com/ru/post/1261237/


All Articles