# Alignment, placement new and struct with pointer to array of POD

239 views

### Daniel

Dec 13, 2015, 1:10:14 PM12/13/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

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

### Martin Bonner

Dec 14, 2015, 8:00:20 AM12/14/15
to
{ edited by mod to shorten lines to ~70 characters. -mod }
I don't think it does. Imagine a crazy system where size_t was unsigned
short which was 32 bits, pointers were 32 bits, but int was 128 bits.
sizeof(storage_type) would be 64 bits, and the ints would not be aligned
correctly. I think you need to define:
struct BB { struct B b; int i[1] };
typedef typename std::aigned_storage<sizeof(B),
alignof(B)>::type storage_type;

size_t length = 10;
char* storage = new char[sizeof(storage_type)+(length-1)*sizeof(int)];
B* pb = new(storage)B();
auto pbb = reinterpret_cast<BB*>(storage);
pb->p = new(&pbb->i)int[length];

### Daniel

Dec 15, 2015, 8:10:17 AM12/15/15
to

On Monday, December 14, 2015 at 8:00:20 AM UTC-5, Martin Bonner wrote:
> On Sunday, 13 December 2015 19:10:14 UTC+1, Daniel wrote:

> > 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?

> I think you need to define:
> struct BB { struct B b; int i[1] };
> typedef typename std::aigned_storage<sizeof(B),
> alignof(B)>::type storage_type;
>
> size_t length = 10;
> char* storage = new char[sizeof(storage_type)+(length-1)*sizeof(int)];
> B* pb = new(storage)B();
> auto pbb = reinterpret_cast<BB*>(storage);
> pb->p = new(&pbb->i)int[length];
>
Thank you very much! that definitely helps my understanding. But did you
mean to write BB instead of B in the typedef for storage_type?

Best regards,
Daniel

### Martin Bonner

Dec 15, 2015, 3:00:17 PM12/15/15
to

On Tuesday, 15 December 2015 14:10:17 UTC+1, Daniel wrote:
> On Monday, December 14, 2015 at 8:00:20 AM UTC-5, Martin Bonner wrote:
> > On Sunday, 13 December 2015 19:10:14 UTC+1, Daniel wrote:
>
> > > 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?
>
> > I think you need to define:
> > struct BB { struct B b; int i[1] };
> > typedef typename std::aigned_storage<sizeof(B),
> > alignof(B)>::type storage_type;
> >
> > size_t length = 10;
> > char* storage = new char[sizeof(storage_type) +
> > (length-1)*sizeof(int)];
> > B* pb = new(storage)B();
> > auto pbb = reinterpret_cast<BB*>(storage);
> > pb->p = new(&pbb->i)int[length];
> >
> Thank you very much! that definitely helps my understanding. But did you
> mean to write BB instead of B in the typedef for storage_type?

Yes!

(and apologies to mod for failing to format correctly last time)

### evansl

Jan 11, 2016, 7:50:17 AM1/11/16
to

On Sunday, December 13, 2015 at 12:10:14 PM UTC-6, 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();
>
> 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?
>
Wouldn't using std::aligned_union:

http://www.cplusplus.com/reference/type_traits/aligned_union/

be simpler? IOW:

using storage_type = aligned_union<Len,A,B>::type;

The only thing that needs to be calculated would be the Len
template parameter, which would just be the max of
the sizeof B and A.

HTH.

-regards,
Larry