5

A line of code is worth a thousand words :) Here is my problem:

/* Platform specific 16-byte alignment macro switch.
   On Visual C++ it would substitute __declspec(align(16)).
   On GCC it substitutes __attribute__((aligned (16))).
*/
#define ALIGN_16 ...

struct ALIGN_16 A {...};

A* ptr = new A;
A* ptr2 = new A[20];

assert(size_t(ptr) % 16 == 0);

for (int i=0; i<20; ++i)
    assert(size_t(ptr2+i) % 16 == 0);

assert(sizeof(A) % 16 == 0);

Can I expect that all assertions pass on platforms with SSE support? Thank you.

EDIT. Partial answer. I did some test with VS2008, GCC and ICC. MS compiler did align both ptr and ptr2, but GCC and ICC failed to align ptr2.

watson1180
  • 2,015
  • 1
  • 18
  • 24
  • Just out of my head. I was wandering, if every element of the array is aligned as well. – watson1180 Dec 15 '10 at 00:22
  • 2
    Elements of a properly-allocated array are guaranteed by the standard to be properly aligned for the type in question. However, that alignment is an implementation detail and could in theory be to one byte (i.e. packed alignment.) – Jonathan Grynspan Dec 15 '10 at 00:30

2 Answers2

4

Is there any guarantee of alignment of address return by C++'s new operation?

In other words, you can use the standard to justify your assumption that it should work, but in practice, it may blow up in your face.

Visual C++ 6 did not align doubles allocated via new properly, so there you go.

Community
  • 1
  • 1
MSN
  • 53,214
  • 7
  • 75
  • 105
  • What about newer compilers? GCC 4.xx and VS 2008? – watson1180 Dec 15 '10 at 01:09
  • 1
    I don't know of any compilers which provide 16-byte alignment with `new` or `malloc`, meaning that in practice, the asserts will fail. – jalf Dec 15 '10 at 08:43
  • @jalf, yup, that's what I figured. I suppose it's "supported" with C++0x, but considering that HeapAlloc guarantees 8 bytes indirectly (since the default packing option is 8-byte alignment for windows data structures), I doubt this will happen any time soon. – MSN Dec 15 '10 at 23:45
1

C++0x provides a new construct (in [meta.type.synop] 20.7.6.6 other transformations):

std::aligned_storage<Length, Alignment>

which is guaranteed to be always correctly aligned as far as I recall.

The second parameter is optional, and defaults to the most stringent requirement possible (so that it's always safe not to precise it, but that you may pack your types more compactly if you are willing to try).

Apart from bugs, the compiler is bound to honor the requirement. If you do not have C++0x, this may be found in the tr1 namespace or on Boost.

You're the only one who can test that your particular compiler does honor this request :)

Note: on gcc-4.3.2, it is implemented as:

template<std::size_t _Len, std::size_t _Align = /**/>
struct aligned_storage
{
  union type
  {
    unsigned char __data[_Len];
    struct __attribute__((__aligned__((_Align)))) { } __align;
  };
};
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • The objects are allocated with `new` though, which (usually) doesn't respect specific alignment requirements. (It usually just gives you 8-byte aligned memory, which is good enough for most purposes) – jalf Dec 15 '10 at 08:44
  • @jalf: but the standard mandates that `new` returns a suitably aligned piece of memory (from 3.7.4.1 [basic.std.dynamic.allocation] $2), unless I don't understand the *so that it can be converted to a pointer of any complete object type with a fundamental alignment requirement (3.11)* and from 3.11 [basic.align] $2 *A fundamental alignment is represented by an alignment less than or equal to the greatest alignment supported by the implementation in all contexts, which is equal to alignof(std::max_align_t) (18.2).* – Matthieu M. Dec 15 '10 at 09:01
  • ... Therefore I would say that if `new` only returns 8-byte aligned values and `std::max_align_t` is superior to 8, then the implementation is non-conforming. – Matthieu M. Dec 15 '10 at 09:01