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

228 views
Skip to first unread message

Daniel

unread,
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

unread,
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

unread,
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

unread,
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

unread,
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

evansl

unread,
Jan 12, 2016, 8:30:18 AM1/12/16
to
[snip]
OOPS. The Len parameter to aligned_union must be a constant,
and it's not since it depends on length, which is a runtime
value.

Sorry for noise :(
Reply all
Reply to author
Forward
0 new messages