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

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

242 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 :(
0 new messages