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

    From Daniel@21:1/5 to All on Sun Dec 13 12:01:40 2015
    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! ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Martin Bonner@21:1/5 to Daniel on Mon Dec 14 06:52:14 2015
    { edited by mod to shorten lines to ~70 characters. -mod }

    On Sunday, 13 December 2015 19:10:14 UTC+1, 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?

    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! ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Daniel@21:1/5 to Martin Bonner on Tue Dec 15 07:08:29 2015
    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


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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Martin Bonner@21:1/5 to Daniel on Tue Dec 15 13:55:01 2015
    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)


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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From evansl@21:1/5 to Daniel on Mon Jan 11 06:46:35 2016
    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


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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From evansl@21:1/5 to evansl on Tue Jan 12 07:21:44 2016
    On Monday, January 11, 2016 at 6:50:17 AM UTC-6, evansl wrote:
    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.
    [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! ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)