Today I have found an interesting case of the dual libstdc++ ABI affecting compatibility of libraries.
Long story short, I have two libraries that both use std::regex internally. One is built with the CXX11 ABI and one is not. When these two libraries are linked together in one executable, it crashes on startup (before main
is entered).
The libraries are unrelated and do not expose interfaces that mention any std::
types. I thought such libraries should be immune to dual ABI issues. Apparently not!
The issue can be reproduced easily this way:
// file.cc
#include <regex>
static std::regex foo("(a|b)");
// main.cc
int main() {}
// build.sh
g++ -o new.o file.cc
g++ -o old.o file.cc -D_GLIBCXX_USE_CXX11_ABI=0
g++ -o main main.cc new.o old.o
./main
And the output is:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
The issue persists whatever I do. file.cc
can be made into two separate source files, compiled into separate shared libraries, the two std::regex
objects may have different names, they can be made global, static or automatic (one will need to call corresponding functions from main
then). None of this helps.
Apparently (this is what comes out of my short investigation) the libstdc++ regex compiler has some kind of internal static data that stores std::string
, and when two ABI-incompatible pieces of code try to use that data, it gets conflicting ideas about the layout of std::string
objects.
So my questions are:
- Is there a workaround for this problem?
- Should this be considered a bug in libstdc++?
The problem is reproducible in several versions of g++/libstdc++ (I tried a few from 5.4 to 7.1). It doesn't occur with libc++.
_GLIBCXX_USE_CXX11_ABI=0
". This is not a problem in and by itself. It works perfectly well when the entire program is built with_GLIBCXX_USE_CXX11_ABI=0
. If as you saystd::regex
is not usable with the old ABI, libstdc++ should immediately#error
if_GLIBCXX_USE_CXX11_ABI
is defined to be 0 when<regex>
is included. I didn't know libc++ doesn't have dual ABIs, thanks! – Cardwell