[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