[cfe-dev] operator new alignment assumptions
Stephan Bergmann via cfe-dev
cfe-dev at lists.llvm.org
Mon Apr 16 01:50:00 PDT 2018
On 16/02/17 13:34, Stephan Bergmann via cfe-dev wrote:
> On 02/16/2017 02:34 AM, Richard Smith wrote:
>> On 13 February 2017 at 06:55, Stephan Bergmann <sbergman at redhat.com
>> <mailto:sbergman at redhat.com>> wrote:
>> * At least with the wording from P0035R4, it is unclear to me what
>> the alignment requirements in
>>
>> struct S { char a[25]; };
>> S * func() { return new S(); }
>>
>>
>> are. When compiled at -O for x86_64-unknown-linux-gnu, Clang trunk
>> apparently assumes that the pointer returned from operator new is
>> 16-byte aligned (writing to it with movaps). But the requirements
>> for that operator new in [new.delete.single] merely states that it
>> "allocates storage suitably aligned to represent any object of that
>> size", and I don't think there is a type of size 25 with a stricter
>> alignment requirement than 1 for that target.
>>
>>
>> Yes, you're right that this is at best unclear and at worst says that
>> our assumption is not valid for allocations that are not a multiple of
>> the allocator alignment. This is the subject of C++ core issue 2207
>> (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2207, but
>> there's no information on the public version of the issues list yet);
>> there generally seemed to be consensus in committee discussion that
>> global non-array non-aligned operator new should provide sufficient
>> storage for any object with a fundamental alignment that fits in the
>> storage, not just for fundamental alignments that divide the allocated
>> size.
>>
>> For instance, we want to guarantee that this sort of thing works:
>>
>> S *p = func();
>> static_assert(sizeof(long double) <= 25);
>> new (p->a) long double; // ok, 'a' is suitably aligned for 'long double'
>>
>> Is this assumption causing problems in practice?
>
> Don't know of any. I stumbled across all this when seeing that the
> Firebird DBMS has a global operator new replacement that generally does
> merely 8-byte alignment on x86-64. But I haven't come across an issue
> related to this fits--vs.--matches-exactly size assumption.
Revisiting this now, I think I /do/ see a problem in practice after all
with Clang making too aggressive assumptions about the aligned-ness of
storage returned by "plain" global operator new, at least with the
Firebird 3.0 that is bundled by LibreOffice:
Firebird replaces that "plain" global operator new, which gets called
with an argument of 24, and recent Clang (on both Linux and macOS
x86-64) uses movaps (requiring 16-byte aligned memory) on the result.
(And the result happens to be only 8-byte aligned, causing a SEGV.)
According to the x86-64 SysV ABI, a struct with a 16-byte alignment
requirement would need to have a size that is a multiple of 16 bytes, so
Firebird's operator new replacement should be OK returning merely 8-byte
aligned storage for a request of 24 bytes.
(It is unfortunate that
<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2207> still
only says "[Detailed description pending.]")
More information about the cfe-dev
mailing list