Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Placement new, alignment, and struct with pointer to POD

35 views
Skip to first unread message

Daniel

unread,
Dec 12, 2015, 12:09:52 PM12/12/15
to
I'm trying to understand the rules for alignment with placement new.

If we have

struct A
{
size_t length;
};

my understanding (please correct me if I'm wrong) is that this results in a
data structure that is properly aligned:

typedef typename std::aligned_storage<sizeof(A),
alignof(A)>::type storage_type;

char* storage = new char [sizeof(storage_type)];
A* pa = new(storage)A();

But what if we have

struct B
{
size_t length;
int *p;
};

and wish to allocate storage for B and p with placement new from the same storage?

Does this satisfy alignment rules?

typedef typename std::aligned_storage<sizeof(B),
alignof(B)>::type storage_type;

size_t length = 10;
char* storage = new char [sizeof(storage_type)+length*sizeof(int)];
B* pb = new(storage)B();

pb->p = new(storage + sizeof(storage_type))int[length];

Thanks,
Daniel

Öö Tiib

unread,
Dec 12, 2015, 7:33:28 PM12/12/15
to
On Saturday, 12 December 2015 19:09:52 UTC+2, Daniel wrote:
> I'm trying to understand the rules for alignment with placement new.
>
> If we have
>
> struct A
> {
> size_t length;
> };
>
> my understanding (please correct me if I'm wrong) is that this results in a
> data structure that is properly aligned:
>
> typedef typename std::aligned_storage<sizeof(A),
> alignof(A)>::type storage_type;
>
> char* storage = new char [sizeof(storage_type)];
> A* pa = new(storage)A();

Seems that you pointlessly manufacture that 'storage_type' there.

// that looks better and works
storage_type* storage = new storage_type;
A* pa = new(storage)A();

// that also works since new provides maximally aligned storage
char* storage = new char [sizeof(A)];
A* pa = new(storage)A();

The likes of that 'storage_type' are typically used to reserve space
in automatic storage or as a data member of class:

// in automatic storage
storage_type storage;
A* pa = new(&storage) A();

>
> But what if we have
>
> struct B
> {
> size_t length;
> int *p;
> };
>
> and wish to allocate storage for B and p with placement new from the same storage?
>
> Does this satisfy alignment rules?
>
> typedef typename std::aligned_storage<sizeof(B),
> alignof(B)>::type storage_type;
>
> size_t length = 10;
> char* storage = new char [sizeof(storage_type)+length*sizeof(int)];
> B* pb = new(storage)B();
>
> pb->p = new(storage + sizeof(storage_type))int[length];
>

It isn't guaranteed that alignment requirements for 'int' are not stricter
than alignment requirements for that 'B'. It is unlikely that you can find
any C++11 compiler where these are stricter but world may change.

Also if there was 'long double' instead of 'int' then alignment requirements for it are often stricter than for the 'B' of yours and then your program
would not work correctly.

Following code is bit more paranoid about that possible padding. When
padding is zero then compiler will likely figure it out and optimize
away:

constexpr size_t padding = (alignof(int) - (sizeof(B) % alignof(int))) % alignof(int);

size_t length = 10;
char* storage = new char [sizeof(B) + padding + sizeof(int)*length];

B* pb = new(storage) B();

pb->length = length;
pb->p = new(storage + sizeof(B) + padding) int[length];

0 new messages