[cfe-dev] C++11 ABI Compatibility and Static Initialization
Kevin Locke
kevin at kevinlocke.name
Mon Apr 7 15:11:31 PDT 2014
Hello All,
I've been trying to track down an EXC_BAD_ACCESS error (Bus error: 10)
which occurs during static initialization when linking a program using
boost to a library using boost. The problem occurred, for me, with
QuantLib, but it has been reported to occur with mlpack[1] and likely
affects other boost-using libraries as well. I have determined that
the issue occurs when a library is compiled with -std=c++11 and the
program is not (or vice versa).
Now that I have identified that the issue is C++11 ABI compatibility,
I can easily avoid the issue on my systems. However, I have brought
it to your attention in the hopes that it can either made easier to
identify or the compatibility can be improved to save future users the
effort spent debugging to identify the same issue.
For reference, the issue occurs when using "Apple LLVM version 5.1
(clang-503.0.38) (based on LLVM 3.4svn)" on Mac OS X 10.9.2 with Boost
1.55.0 using the following example program (please excuse the abuse of
Boost internals to make a minimal test case):
-8<--libcrash11.cpp---------------------------------------------------
#include <boost/math/special_functions/lanczos.hpp>
double libfunc() {
return boost::math::lanczos::lanczos17m64::lanczos_sum(1.0);
}
-8<--libcrash11.cpp---------------------------------------------------
-8<--crash11.cpp------------------------------------------------------
#include <boost/math/special_functions/lanczos.hpp>
int main(int,char**) {
boost::math::lanczos::lanczos17m64::lanczos_sum(1.0);
return 0;
}
-8<--crash11.cpp------------------------------------------------------
Compiled as follows:
clang++ -dynamiclib -o libcrash11.dylib libcrash11.cpp
clang++ -std=c++11 -L. -lcrash11 -o crash11 crash11.cpp
Now the binary compiled in C++11 mode has
double boost::math::lanczos::lanczos17m64::lanczos_sum<double>(double const&)::num
inside the .__TEXT.__const segment while the other has this symbol inside
the .__DATA.__data segment.
Executing crash11 in a debugger shows that the program stops with
EXC_BAD_ACCESS when attempting to initialize the copy of
double boost::math::lanczos::lanczos17m64::lanczos_sum<double>(double const&)::num
inside the crash11.__TEXT.__const segment (which is presumably mapped
read-only).
As a non-expert, I would guess that in C++11 the value of the symbol
can be determined at compile time and placed in the const segment
while in C++98 mode it must be initialized at runtime and that when
linked together the initialization is applied to both occurrences of
the symbol, causing the crash. But I may be completely off-base with
this guess.
So, my question to you is: Can the situation be improved? Either by
avoiding the crash by applying the initialization only to the symbol
in .__DATA.__data or could it generate a linker or loader error with a
message that indicates the C++11 ABI as a potential cause of the
incompatibility? Or perhaps something else?
In either case users would be advised to not link different C++
dialects together. But I'm afraid we users are perpetually finding
ways to screw such things up (or, at least, I am).
Cheers,
Kevin
1. http://trac.research.cc.gatech.edu/fastlab/ticket/296
More information about the cfe-dev
mailing list