[cfe-dev] Problem with libc++/libstdc++ interoperability on OS X

Florian Pflug fgp at phlo.org
Wed Oct 30 18:09:19 PDT 2013


On Jan29, 2013, at 19:13 , Howard Hinnant <hhinnant at apple.com> wrote:
> On Jan 28, 2013, at 10:39 PM, Florian Pflug <fgp at phlo.org> wrote:
>> Now, libstdc++'s std::runtime_error contains an std::string which contains the error message, but libc++'s std::string is ABI-compatible with libstdc++'s. libc++ seemingly tries to overcome that obstacle by implementing a simple non-mutable string which is supposed to be ABI-compatible with libstdc++, called libcpp_nmstr.
>> 
>> Unfortunately, this is where things start to break. My version of libc++ doesn't seem to get libcpp_nmstr quite right. libstdc++ seems to use a 4-byte refcount field, followed by 4 bytes of padding. According to the dissassembler, my libc++ OTOH seems to have it the other way around, and ends up incrementing the padding instead of the refcount. Since these increments are invisible to libstdc++'s std::string destructor, it ends up freeing the same block multiple times :-(
>> 
>> To make things worse, the relevant code in libc++ isn't in the headers, but instead compiled into the library. Thus, whoever links against libc++ on OS X potentially gets the broken version of std::runtime_error. Which, as it turns out, is everybody, since libSystem pulls in libdispatch which in turn pulls in libc++.  So that finally explains the crashes I've been seeing - if a build is unlucky enough to not inline std::runtime_error's copy-constructor, operator= or destructor *and* the dynamic linker chooses to pick the symbol from libc++, things go south…
>> 
>> Has anyone an idea how to work around this?
> 
> The only workaround I'm aware of at the moment is to not mix libstdc++ and libc++.  This logic for this code has been both moved and fixed.  It is now in the libcxxabi project:

FWIW, I reported this to Apple (bug 13100815) and was just informed that the bug is supposed to be fixed in OS X Mavericks, and will not be fixed in earlier releases :-(.

Since you *cannot* avoid mixing libstdc++ and libc++ on OS X nowadays, due to libSystem's habit of pulling in libc++ (via libdispatch), that leaves std::runtime_error broken on at least 10.8 Mountain Lion and probably on earlier versions too. The only "workaround" seems to be to juggle compiler flags until you hit a combination that hides the problem (e.g. combination that inlines std::runtime_error's copy constructor). Unfortunately, and such workaround is very fragile - arbitrary code changes can cause the problem to resurface.

best regards,
Florian Pflug





More information about the cfe-dev mailing list