[cfe-dev] libc++ ABI versioning

Jorgen Tjerno jorgen at uberent.com
Wed Jun 11 20:01:42 PDT 2014


So does this mean I need to be linking statically with libc++? :/

- Jørgen.


On Wed, Jun 11, 2014 at 10:49 AM, Marshall Clow <mclow.lists at gmail.com> wrote:
>
> On Jun 11, 2014, at 10:19 AM, Jorgen Tjerno <jorgen at uberent.com> wrote:
>> On Wed, Jun 11, 2014 at 6:48 AM, Marshall Clow <mclow.lists at gmail.com> wrote:
>>>
>>> On Jun 9, 2014, at 7:26 PM, Jorgen Tjerno <jorgen at uberent.com> wrote:
>>>> On Mon, Jun 9, 2014 at 6:56 PM, Richard Smith <richard at metafoo.co.uk> wrote:
>>>>> On Mon, Jun 9, 2014 at 6:32 PM, Jorgen Tjerno <jorgen at uberent.com> wrote:
>>>>>>
>>>>>> I've noticed that Xcode 4.6 and Xcode 5.1 ship with headers that have
>>>>>> different layouts for std::ifstream. sizeof(std::ifstream) is 448 for
>>>>>> 4.6, and 576 on 5.1. You can see my test case here:
>>>>>> https://gist.github.com/anonymous/bd0db5e4bcb307b70506
>>>>>>
>>>>>> How does clang/libc++ ensure that the executable runs with the right
>>>>>> libc++ version for headers it was built with? I can run the binaries
>>>>>> produced by Xcode 4.6 on a machine that has a newer libc++, and I can
>>>>>> run the binaries produced by 5.1 on a machine that has an older
>>>>>> libc++. I would assume that if I built with headers that give me a
>>>>>> smaller size than what is expected by libc++, that would be cause the
>>>>>> newer libc++ to trash memory beyond the end of my object. Am I missing
>>>>>> something?
>>>>>>
>>>>>> I was unable to find any resources on how libc++ ABI versioning works
>>>>>> other than the "major ABI version" -- which is 1.
>>>>>>
>>>>>> The specific problem I'm seeing is that it seems that when I link with
>>>>>> a static library that was built with the older libc++ version, a
>>>>>> translation unit built with the new libc++ ends up using the wrong
>>>>>> (old) value for the construction symbol at runtime
>>>>>>
>>>>>> (__ZTCNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE0_NS_13basic_istreamIcS2_EE,
>>>>>> or '
>>>>>>  construction vtable for std::__1::basic_istream<char,
>>>>>> std::__1::char_traits<char> >-in-std::__1::basic_ifstream<char,
>>>>>> std::__1::char_traits<char> >' according to c++filt).
>>>>>
>>>>>
>>>>> Looks like the difference is probably due to the std::filebuf subobject. Did
>>>>> that type also change size? Did std::basic_streambuf<char>?
>>>>
>>>> Yep, filebuf did, and that does seem to account for the difference in size.
>>>>
>>>> themac:~ jorgen$ ./foo-modern
>>>> sizeof(std::ifstream)=576, offset=0
>>>> sizeof(std::istream)=168, offset=0
>>>> sizeof(std::ios)=152, offset=424
>>>> sizeof(std::ios_base)=136, offset=424
>>>> sizeof(std::filebuf)=408, offset=0
>>>> sizeof(std::basic_streambuf<char>)=64, offset=0
>>>>
>>>> themac:~ jorgen$ ./foo
>>>> sizeof(std::ifstream)=448, offset=0
>>>> sizeof(std::istream)=168, offset=0
>>>> sizeof(std::ios)=152, offset=296
>>>> sizeof(std::ios_base)=136, offset=296
>>>> sizeof(std::filebuf)=280, offset=0
>>>> sizeof(std::basic_streambuf<char>)=64, offset=0
>>>
>>> Looks like this commit was the culprit:
>>>
>>> r162601 | hhinnant | 2012-08-24 14:20:56 -0700 (Fri, 24 Aug 2012) | 31 lines
>>>
>>> It added a new member variable
>>>        state_type __st_last_;
>>>
>>> to the basic_filebuf object, and that variable is 128 bytes long.
>>>
>> So why is this not an ABI-breaking change?
>>
>> What causes a program built against the earlier version of
>> std::ifstream to correctly execute on a machine that has the latest
>> version of std::ifstream that expects a larger layout?
>
> I think it was an ABI-breaking change.
> I also believe that it was done w/o realizing that it was breaking the ABI.
>
> — Marshall




More information about the cfe-dev mailing list