G++ new ABI problems - c++

I got a problem with the new ABI introduced for C++11 in GCC. After upgrading to GCC 5.3 my project does no longer compile. The error messages I get are simple:
undefined reference to `tokenize(std::__cxx11::basic_string' ...more characters
or
undefined reference to `extract(std::string const&)'
So, it looks like I messed something up and GCC is unable to decide whether I want the old ABI or the new one (the __cxx11:: part is missing from some error messages, and present in others)?
I tried several solutions to resolve the issue:
passing -D_GLIBCXX_USE_CXX11_ABI=0 to GCC,
passing -D_GLIBCXX_USE_CXX11_ABI=1 to GCC,
setting the macro directly in source code,
setting the abi_tag attribute on the declarations GCC complained about when passed the -Wabi-tag flag,
Unfortunately, neither of them worked (i.e. allowed the code to compile). The one thing I know is that only functions returning std::string or taking it as a parameter fail to link. Which is to be expected, given what I read about the problem on the Internet. I was unable to reproduce the issue in a simple, example program to present it here.
Is there any obvious solution to my problem, that I am missing?

This error indicates that you're linking to some code or library that has not been recompiled by gcc 5.3, and was compiled by an earlier version of gcc, using the earlier version of the ABI.
If you are linking with some external libraries, besides the standard C++ library, those external libraries need to be recompiled (and reinstalled).
If you are not linking with any external libraries, and you are only linking together your own code, some of your source modules must not've been recompiled yet. Recompile everything. Make sure to wipe all existing object modules, with make clean, or the equivalent for whatever build system you're using.

Related

Boost linking error - single undefined reference

I'm having an odd linking problem with Boost (version 1.58). I'm building with g++ 4.8 on Ubuntu 15.10.
I get the following error:
undefined reference to
'boost::program_options::options_description::options_description(std::string
const&, unsigned int, unsigned int)' collect2: error: ld returned 1
exit status
What's strange is that all other symbols from lboost_program_options are found; options_description is the only undefined reference. If I comment out uses of options_description but keep uses of positional_options_description (which I'm also using) then the whole program compiles and links flawlessly. I am linking with -lboost_program_options, and if I remove this then as expected there are 8 missing boost::options_description symbols.
For a long time linking has worked correctly. Without any build system changes that I'm aware of it suddenly broke. The only systems level change was an upgrade to Ubuntu 15.10, which I don't think should have affected anything.
Any thoughts or suggestions appreciated.
Update: After lots of fiddling I got this working again, although I'm not sure what did it. I'm still interested in any answers to what could cause this type of behavior though.
Check that the ABI is compatible (you're using the same compiler version and flags used when compiling the boost libraries).
On Ubuntu, this means using stock GCC with libstdc++.
If you can't, compile your own Boost System and Boost Program Options binaries using your preferred flags.
Similar things prevent code samples from linking on http://coliru.stacked-crooked.com if your compiler is not the same as used when compiling boost there.
I had a similar problem after upgrading to Ubuntu 15.10 with a different symbol missing in a lib belonging to boost::program_options.
It helped to simply clean up the whole project by throwing away all object files etc. and recompiling it from scratch.

Trouble linking C++ with Xcode 5

So I have this legacy project, which I am trying to bring to iOS 7 and Xcode 5. And by legacy, I mean real legacy. Like 2004 legacy.
Anyhow, I am trying to build this thing, and it spits out a few libraries, including some common third party libs. When linking, I get errors like these:
Undefined symbols for architecture ${arch}:
"google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)"
Upon examination with nm, the old (arm only) binary library still included in the project contains this:
U __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE
00000a8c T __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE
00002b28 S __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEEPNS0_2io17CodedOutputStreamE.eh</code>
The new library (universal), created when I run the project through Xcode 5 (and thus, clang/llvm) contains this:
U __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE
00000514 T __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE
00000b2c S __ZN6google8protobuf8internal14WireFormatLite10WriteBytesEiRKSsPNS0_2io17CodedOutputStreamE.eh
To me, it looks like the parameters are missing in the mangled name.
Is this normal and I need to look somewhere else?
Or if this is the problem: Any idea how to solve it?
EDIT: I mixed up OLD and NEW. I left the original post unchanged
The old, arm only libary seems to indicate:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)
Which has all the hallmarks of being compiled with libstdc++.
The new universal library indicates:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, google::protobuf::io::CodedOutputStream*)
This has all the hallmarks of being compiled with libc++
Your link error indicates that there is a problem finding:
google::protobuf::internal::WireFormatLite::WriteBytes(int, std::string const&, google::protobuf::io::CodedOutputStream*)
This would be the case if the code linking to the library was compiled using libstdc++ and, because your new universal library is compiled using libc++ the code will not link.
You have to compile everything with the same libc++/libstdc++ support, you cannot mix and match as they will refuse to link. Make sure that every element in your project is compiled using the same C++ Standard Library and the link error should be resolved.
In general, demangling the symbols (using c++filt) allows you to see the proper signatures, and in the case of this code, once you start seeing std::__1:: in the symbols, it indicates that the library was compiled using libc++, and when you see the link failing with unadorned std:: symbols (i.e. without the inner __1::), then it indicates that the item performing the linking is using libstdc++.
Are you perhaps mixing and matching SDKs or compilers? Name mangling might differ between compilers. The only other thing I know that might affect name mangling is the 'extern "C"' keyword, but that usually turns it off completely, so I don't think that's it.
So, if the old code was still built with GCC 2.x and your new code is clang-built, they probably just mangle differently.
Does the error message really say $(arch) ? Not a particular architecture? If it gave a concrete architecture, I'd expect that you have one project that builds e.g. for arm5 and arm6, linking in a library that only has one of these architectures. Then it usually complains about the symbols in that library not being available, I think.

Which libraries do I need to link against with MinGW for an object file built with Clang?

I'm using an object file built with Clang. But no matter what library arguments I pass to ld.exe, it seems to always spit back unresolved references, stuff like memcpy, Standard library, stuff, and implementation stuff like _cxa_atexit.
What libraries (and in what order?) do I need to pass to the MinGW linker to get it to link my object file into an executable?
Edit:
I changed the triple from "i686-pc-mingw" to "i686-pc-mingw32" and it solved most of the problems- Clang does the old D3D9 trick of "Silently fail when the input is clearly wrong and there's no way the output could be correct". But I'm left with just two unresolved externals- it's some std::_Hash_impl for float and double, with no change. The program is just "Hello, World!". Curiously, neither clang++.exe nor g++.exe have a problem with compiling the source, but if I compile it using the Clang C++ API to .o, and then pass it back to MinGW, I get the unresolved externals.
In general, it's not a good idea to use different toolchains when building a binary. It is entirely possible that the different tools' ideas of names of symbols won't match up.
Still, trying to answer your actual quesiton:
-lstdc would be a minimum requirement and -lstdc++ if it's C++ code. without knowing what your code does, it's impossible to say if you need more of them.

mixing compiler

I am wondering if it is possible to link a c++ program compiled with gcc4.2 with a shared c++ library that is compiled in a later version like gcc4.5.
I've tried to do this, but have run into some different kind of problems.
When compiling the shared library gcc5.3 I get a message saying:
*"malloc: error for object 0x7fff707d2500: pointer being freed was not allocated
set a breakpoint in malloc_error_break to debug"*.
If I try to compile the shared library with gcc4.6 I get really strange behaviour. The std::stringstream class is not working correctly. The resulting string is empty after writing to the stream.
Is it possible to do this? Or am I trying something that is impossible? I was hoping that this was possible since I'm linking the lib dynamically. Btw I'm running on MacOSX.
BR
Beginning with gcc 3.0, g++ follows the Itanium ABI, so in theory there should be no problem. However, g++ 4.2 has CXXABI_1.3.1 whereas g++ 4.5 has CXXABI_1.3.4 (see here). Therefore I'd be careful. One does not bump up revision numbers if there are no differences.
Further, the glibc++ has gone through 5 revisions between those versions, which may be one reason why you see std::stringstream do funny things.
Lastly, there exist many config options (such as for example making strings fully dynamic or not) which affect the behaviour and compatibility of the standard library directly. Given two (random, unknown) builds, you cannot even know that they have the same config options.
In my experience the ABI compatibility means that C++ libraries can link to each-other without problems.
However, because C++ uses so many inline functions this doesn't mean much.
If the Standard C++ Library used all inline functions or used all library functions then you could use code compiled with older versions of GCC with newer versions.
But it doesn't. The library mixes inline and external library code. This means that if something is changed in std::string, or std::vector or locales or whatever, then the inlined code from the old GCC is out of sync with the library code linked from the new GCC.

Please explain this linking error: referenced in section .rodata

I am doing a build on a 32bit SLES10 machine. Using GCC 3.4.2
Here is a sample error
`.L8245' referenced in section `.rodata' of CMakeFiles/myproj.dir/c++/util/MyObj.o: defined in discarded section
`.gnu.linkonce.t._ZN5boost9re_detail9reg_grep2INS0_21grep_search_predicateIPKcSaIcEEES4_cNS_12regex_traitsIcEES5_S5_EEjT_T0_SA_RKNS_14reg_expressionIT1_T2_T3_EEjT4_' of CMakeFiles/myproj.dir/c++/util/MyObj.o
This is typically due to 2 different .cpp's being compiled with different compiler switches - but also using the same templates. The generated template instantiations may differ in what they define/reference, and if the instantiation that is selected doesn't define/refer to the exact same symbols as the ones that got discarded you may get this error.
Validate that all your .cpp's are compiled with the exact same compiler switches and defines. If this isn't possible, reorder the .obj files on the linker commandline, in particular try to move the .obj files mentioned in the error message to the end or beginning of the .obj file list.
EDIT:
Also, if you're linking against prebuilt c++ libraries, see if you can duplicate the compiler switches used for building these libraries.
This may be due to using a newer version of binutils. binutils version 2.15 treated this as a non-fatal error, but later versions of binutils changed and so the link started failing. See https://bugzilla.redhat.com/show_bug.cgi?id=191618 for a similar report.
In my case, I was able to get things to link once more by explicitly using binutils 2.16.1, instead of binutils 2.17.