2

I'm getting a strange error I suspect has to do with my system configuration. I am compiling/linking a trivial c++ program using g++ --version = g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609. The default language standard is documented to be c++98, yet even with the -std=c++98 option specified, I am seeing c++11 symbols in the output .o file. This is my test.cpp:

#include <string>
int main() {
  std::string str = "Hello World!";
  return 0;
}

Here are my compile and link commands (with presumably unnecessary explicit language standard option) and associated output:

$ g++ -c -Wall -std=c++98 -o test.o test.cpp
$ g++ -Wall -std=c++98 -o test test.o
$ nm -C test.o
                 U __gxx_personality_v0
0000000000000000 T main
                 U __stack_chk_fail
                 U _Unwind_Resume
                 U std::allocator<char>::allocator()
                 U std::allocator<char>::~allocator()
                 U std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
                 U std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()

Notice the references to __cxx11::*. I presume those are c++11 symbols that the compiler inserted. I get a successful build, but apparently using c++11. Here is the output from ldd:

$ ldd test
    linux-vdso.so.1 =>  (0x00007ffc381f5000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f6548d48000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f6548b32000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6548768000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f654845f000)
    /lib64/ld-linux-x86-64.so.2 (0x000055785493c000)

For my real project, I have to link to third party libs that are c++98 but am unable to do so because of this compiler issue. My object files are looking for c++11 symbols in those libs but can't find them. Any insights?

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
Cosmo
  • 491
  • 7
  • 14
  • Looks to me that your libstdc++ was compiled with c++11, so you might need to use a different one to get the non-c++11 symbols. Not 100% sure, though, since I don't know for sure whether the shared lib could include both c++11 and older symbols – awksp Feb 28 '17 at 16:44
  • 1
    C++11 and C++98 are *conformance level* of the language. To link a library to produce executable, the library must have been developped with the same build system. You should not link together object produced by different compilers *whatever language conformance level* you declare. – Serge Ballesta Feb 28 '17 at 16:53
  • 2
    As a rule of thumb, C++ code cannot be linked to a "third party library" unless it was build with the same exact C++ compiler. Of course, a compiler can offer ABI compatibility with other versions of the same compiler, whether or not this ABI compatibility is provided by -std=c++98, is unclear. All that this option does is specify the language standard against which the code gets compiled. – Sam Varshavchik Feb 28 '17 at 16:53
  • 3
    GCC somewhere in the v5 era changed their ABI version to have a small-string-optimized `std::string`, instead of C++11-incompatible copy-on-write string implementation. This is alright even for C++03/98 I think, because they are still conforming. I suspect you can fix your issue by forcing it or your standard library to use the older ABI. Since the string is just a template, if you are lucky it may work without recompilation of the standard library. – Johannes Schaub - litb Feb 28 '17 at 18:06
  • The name __cxx11 is misleading, it could just as well have been __version_7, but since it was introduced at the same time as C++11... It doesn't mean the compiler is using C++11, it is just an ABI detail. – Marc Glisse Feb 28 '17 at 19:37
  • Thanks for the responses. I'm going to work on getting the source for the 3rd party libs and build them myself. If I can't get the source, then I suppose the only other option is to determine the compiler version and platform used and set up a matching VM to do my development on. – Cosmo Feb 28 '17 at 19:43

1 Answers1

3

As described here, the libstdc++ v.6 supports new and old ABI. I had to place

-D_GLIBCXX_USE_CXX11_ABI=0

to the Makefile's g++ command. That took care of the lib incompatibility.

Cosmo
  • 491
  • 7
  • 14
  • 1
    You should prefer defining that macro on the commandline or in the makefile or whatever instead. Defining it in the source file is limiting, fragile, and quite surprising to other people trying to use your code. – rubenvb Mar 01 '17 at 18:27
  • I added `-D_GLIBCXX_USE_CXX11_ABI=0` to the Makefile's g++ command. That's definitely the way to do it. Thanks. – Cosmo Mar 02 '17 at 19:22