http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53646
Bug #: 53646 Summary: Surprising effects of cxx11 vs cxx98 ABI compatibility Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: m...@gcc.gnu.org Created attachment 27611 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=27611 tarball containing testcase As is long known mixing cxx11 and cxx98 code isn't supported. I'm reporting this anyway because I'm not sure that the full consequences of this were realized. Unpack the tarball, then: # cd cxxabi-incompat # make CXX=<path-to-trunk-g++> ... # ./app Segmentation fault # ./app2 Segmentation fault In this specific case the problem is the Rb_tree::equal_range function, which returns a pair, under cxx98 that's POD (returned via registers), under cxx11 it's not POD and returned via invisible reference. I.e. calls from cxx98 to cxx11 version of that function will segfault and vice verso. The testcase consists of two libraries (lib1 lib2), compiled with cxx11 and cxx98 respectively. Both libs don't depend or interact with each other. The app stands for a random application making use of random libraries, calling simple functions in them, which themself don't exhibit any ABI problem. I.e. the testcase tries to show a typical situation for application developers using several different 3rd party libraries not under control of that developer. The problem happens because both libs contains a (weak) definition of the equal_range function. As the libs don't control their exports this symbol also is exported. Hence the calls will be resolved to whatever version comes first in dynamic linker search order (that's the reason for the two apps built, once with "-l1 -l2", once with "-l2 -l1"). So, whichever library is first in search order, the other library will resolve its own equal_range call (stemming from the inlined erase) to that first library, and thereby crash because that version was compiled with different c++ ABI. Now, this might all be as designed, but what this "you can't mix c++11 and c++98" means is that an application can't even _link_ against two libraries compiled with different settings, when the libs don't tightly control their exports (which might not be possible on all targets). That's even prohibited if the library authors made sure that the API itself doesn't contain any problematic constructs, for instance just a C API, and c++ is used only internally. In effect this means, that if library authors don't control all their consumers (which is the case for most libraries) they must expect that those will also link against some c++98 libraries, and hence can't make use of c++11 constructs even internally. Furthermore, if one wants to link against a c++11 compiled library (which the typical user won't even know, especially if only used in the internal implementation) the whole stack also needs to be c++11, effectively requiring two versions of every library that somehow uses c++ to be installed. The dynamic linker (or games via separate paths) would have to resolve to the right variants. No distribution is going to do something like this (and not all libraries might even be compilable in c++11 mode), and this effectively prevents c++11 to be used _at all_ in development. This report is a result from a real issue we had: our package management is written in C++, and the library author started using c++11. The applications linking against that component were still at c++98 leading to crashes. I had to advise them to control their exports or stop using c++11. Luckily we were in the position to do the former, but if it had been a third party lib there would have been no way out (rewriting the apps isn't possible because we don't control all of them).