[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