Discussion:
Alignment, placement new and struct with pointer to array of POD
(too old to reply)
Daniel
2015-12-13 18:01:40 UTC
Permalink
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
2015-12-14 12:52:14 UTC
Permalink
{ edited by mod to shorten lines to ~70 characters. -mod }
Post by Daniel
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
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];
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];
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Daniel
2015-12-15 13:08:29 UTC
Permalink
Post by Martin Bonner
Post by Daniel
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?
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
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Martin Bonner
2015-12-15 19:55:01 UTC
Permalink
Post by Daniel
Post by Martin Bonner
Post by Daniel
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?
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)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
evansl
2016-01-11 12:46:35 UTC
Permalink
Post by Daniel
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
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
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
evansl
2016-01-12 13:21:44 UTC
Permalink
Post by evansl
Post by Daniel
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
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?
http://www.cplusplus.com/reference/type_traits/aligned_union/
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.
[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 :(
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Loading...