[cfe-dev] C++11 ABI Compatibility and Static Initialization

Erik Schnetter schnetter at gmail.com
Wed Apr 9 05:56:14 PDT 2014


On Apr 9, 2014, at 1:43 , Kevin Locke <kevin at kevinlocke.name> wrote:

> On Tue, 2014-04-08 at 18:50 -0400, Erik Schnetter wrote:
>> On Apr 7, 2014, at 18:11 , Kevin Locke <kevin at kevinlocke.name> wrote:
>>> 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.
>> 
>> From my reading of the Boost sources, it seems that Boost determines
>> at compile time whether constexpr is available, and uses it if so.
>> This means that Boost consists of different C++ code depending on
>> whether -std=c++11 is used or not. I would assume that this means
>> that the resulting object code should not be expected to work.
>> 
>> My initial reaction is that this is an error in Boost (which could
>> make this distinction at configuration time instead of at compile
>> time), or that Boost should at least detect this problem and abort
>> with an error. Of course, if clang could detect this
>> incompatibility, this would also be good.
> 
> Hi Erik and Mehdi,
> 
> Thanks for considering the issue!  You are quite right about the
> conditional use of constexpr and Boost's decision not to pursue binary
> compatibility across C++ dialects.  A bug report to boost to make the
> error more easily identifiable may be warranted, depending on your
> thoughts on the root of the issue, discussed below.
> 
> I wonder if Boost may have been a bit of a red herring as to whether
> there is a clang issue (or potential improvement) for this case.  So
> I've worked out a more minimal example which does not rely on Boost:
> 
> -8<--libawesome.hpp---------------------------------------------------
> #if __has_feature(cxx_constexpr)
> #define CONSTEXPR_OR_CONST constexpr
> #else
> #define CONSTEXPR_OR_CONST const
> #endif
> 
> inline double dummy(const double* num) {
>    return 1.0L;
> }
> 
> inline CONSTEXPR_OR_CONST double maybe_constexpr(double v)
> {
>   return v;
> }
> 
> template <class Awesome>
> struct awesome_initializer
> {
>   struct init
>   {
>      init()
>      {
>         Awesome::calc_stuff();
>      }
>      void force_instantiate()const{}
>   };
>   static const init initializer;
>   static void force_instantiate()
>   {
>      initializer.force_instantiate();
>   }
> };
> template <class Awesome>
> typename awesome_initializer<Awesome>::init const awesome_initializer<Awesome>::initializer;
> 
> struct awesome
> {
>   static double calc_stuff()
>   {
>      awesome_initializer<awesome>::force_instantiate();
>      static const double num[1] = {
>         maybe_constexpr(1.0)
>      };
>      return dummy(num);
>   }
> };
> -8<--libawesome.hpp---------------------------------------------------
> 
> -8<--libcrash11.cpp---------------------------------------------------
> #include "libawesome.hpp"
> 
> double libfunc() {
>    return awesome::calc_stuff();
> }
> -8<--libcrash11.cpp---------------------------------------------------
> 
> -8<--crash11.cpp------------------------------------------------------
> #include "libawesome.hpp"
> 
> int main(int,char**) {
>    awesome::calc_stuff();
>    return 0;
> }
> -8<--crash11.cpp------------------------------------------------------
> 
> As before, they can be compiled as follows:
> clang++ -dynamiclib -o libcrash11.dylib libcrash11.cpp
> clang++ -std=c++11 -L. -lcrash11 -o crash11 crash11.cpp
> 
> Also as before, executing crash11 will result in an EXC_BAD_ACCESS
> error and program crash.
> 
> It is worth noting that the error can be caused by a header-only
> library shared (possibly as an internal implementation detail) by the
> program and a library on which it depends, even when neither the
> program nor library use any C++11 features.  Also note that only
> fundamental types are passed between the program and the library (in
> the example, only the double returned by the library function), making
> the error all the more unexpected.
> 
> Is there anything which can be done to improve the situation in cases
> like this, or is some hairy static initializer debugging just the
> price that everyone has to pay for making this sort of mistake?

I would have hoped that name mangling catches this problem via a linker error.

-erik

-- 
Erik Schnetter <schnetter at gmail.com>
http://www.perimeterinstitute.ca/personal/eschnetter/

My email is as private as my paper mail. I therefore support encrypting
and signing email messages. Get my PGP key from http://pgp.mit.edu/.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 203 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20140409/eb1e6d9b/attachment.sig>


More information about the cfe-dev mailing list