Reputation: 328
I'm struggling with a linking error. I have 3 modules:
During the linking of the executable C, I receive the following error message:
../../bin/B.so: undefined reference to `ole::compound_document::find_storage(std::string const&)'
The function is defined in library A. If I run utility nm on shared library B, I receive the following output:
0000000001841c70 T ole::compound_document::find_storage(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
U ole::compound_document::find_storage(std::string const&)
It shows two find_storage functions. One of them is defined another is not defined. I'm trying to understand how can it happens. So far unsuccessful. The problem appears under Linux (Ubuntu), compiler: clang-9. On Windows, I can build the libraries and the executable without any problem.
I've tried to create a minimal example, just putting 3 simple modules together with only a few functions. Everything works. The compiler uses only the first definition of the function. I don't understand where the second definition comes from. I suspected some mix of c++ standards but cannot find anything.
Any suggestions will be highly appreciated.
Upvotes: 1
Views: 1637
Reputation: 328
As mentioned by n. 'pronouns' m.The problem was in inconsistent use of -D_GLIBCXX_USE_CXX11_ABI flag. I used c++14 standard, but some projects were compiled with the flag -D_GLIBCXX_USE_CXX11_ABI=1. It was not easy to find out, because I use a lot of 3rd party libraries with conan package manager.
Upvotes: 0
Reputation: 118425
You will need to look for problems in library B's code. std::string
, verbatim, is not something that's expected to be an actual type referenced from an exported symbol, since std::string
is just an alias for a std::basic_string
instance. Narrow this down by looking at symbols of all modules that were linked into library B, and once you identified the module that does, you'll need to figure out why.
Your question does not provide sufficient data to decisively identify the linking problem because, of course, that can only be done by inspecting all the object modules involved in the linking, and inspecting all the source code for the likely violations of the One Definition Rule, or ill-formed code that did not produce a diagnostic, but manifested itself as a link failure.
Therefore, the following answer is meant to be as a general guide to isolating these kinds of linking failure. I don't think this question qualifies to be hammered by the canonical answer.
You have a symbol in the linked shared library that's not getting resolved when linked to an executable, specifically:
ole::compound_document::find_storage(std::string const&)
Just like you ran nm
on the shared library, you can use it on every module that went into the shared library, individually. This will find which object module the unresolved reference came from. If you don't find it, it must've come from the static library you linked with, so repeat your search there.
That reference came from one of the object modules that you used to build the shared library. You will find it this way, it's unlikely to pop into existence of its own.
Once you find the relevant module, you're then on your own, by looking at the actual code that was compiled, and figure out what's up. If you can't figure it out: divide and conquer. Take the object module, and split the source file into two files, half of the functions in each one, compile them separately, and then look and see where the unresolved reference comes from.
Finally: before doing all that, try the low hanging fruit: make clean
, then recompile everything. This has all the hallmarks of a compiler switch, some of the object modules were compiled by a different compiler. If that static library was provided by a third party vendor as a binary blob, it must've been compiled by a different compiler or a different version of your compiler. C++ does not guarantee binary ABI compatibility.
Upvotes: 1