alignment issues

Discussion in 'C++' started by Stephen Horne, Sep 24, 2008.

  1. I understand that the next C++ standard will have features to handle
    the alignment of data types. This is good, but a bit late for me!

    I've been using some template trickery to handle alignment issues for
    some time. What I usually want is a type that takes the same amount of
    space and has the same alignment as some other type, but which doesn't
    have constructors, destructors etc. The idea is that initialisation
    and cleanup can be done with casts, placement new and explicit
    destructor calls, but that this memory-only type can live in a union
    or whatever.

    To get the alignment of an existing type, I use something like...

    template<typename T>
    class CAlign_Of
    {
    private:
    struct CDummy
    {
    char m_Char;
    T m_T;
    };

    public:
    enum { Align = ((size_t) &(((CDummy*) 0)->m_T)) };
    };

    Which I figure should be portable to any platform where char is a
    single byte (though I don't think even that is guaranteed).

    To create the replacement type, however, is a bit more of a problem.
    To create a type the right size, you just use a template struct
    containing and array of chars, but getting the alignment right is the
    problem.

    Using template specialisation to present a range of options isn't too
    problematic, but how to code the options.

    At the moment I have a #ifdef conditional compilation solution. The
    Microsoft VC++ block uses the __declspec(align(n)) non-portable
    solution, which annoyingly only accepts literal integers (as opposed
    to compile-time constants) for the parameter. But for other compilers,
    all I can come up with is the following...

    template<size_t S>
    struct CSpace_For<S, 1> { UInt8 m [ S ]; };

    template<size_t S>
    struct CSpace_For<S, 2> { UInt16 m [(S+1)/2]; };

    template<size_t S>
    struct CSpace_For<S, 4> { UInt32 m [(S+3)/4]; };

    template<size_t S>
    struct CSpace_For<S, 8> { UInt64 m [(S+7)/8]; };

    However, there is no guarantee that any compiler will use the needed
    alignment for these types. It can depend on the platform, the
    compiler, and compiler settings.

    Up until now, I haven't worried because I always knew what compiler I
    was targetting. Now I have a problem - I'm writing a code generator
    that needs to generate variant-record-like types. Those variants will
    have members with types defined outside the generated code, which may
    not be considered aggregates. The whole point of this project is to
    sell it to unsuspecting victims, and I'd like to minimise the victim
    aspect.

    From what I've seen in other code generators, the usual practice is to
    assume a pessimistic alignment, allocate a bit of extra memory, and do
    an align-to-boundary calculation manually such as...

    (address + 15) & ~15

    This worries me because pessimistic may not be pessimistic enough as
    extra hardward features are added that I'm not aware of - I undestand
    that SIMD instructuctions require aligned data, for example, with
    potentially larger alignments than 8 bytes (16 bytes certainly) - and
    who knows what the next 5 years will bring.

    So...

    1. Is there a good portable solution now?
    2. What will the standard C++ solution be?
    3. How consistent are compilers in their non-standard alignment
    handling right now? - e.g. does GCC c++ support an __alignof
    extension similar to that on MS VC++?
    Stephen Horne, Sep 24, 2008
    #1
    1. Advertising

  2. On Wed, 24 Sep 2008 07:13:31 +0100, Stephen Horne
    <> wrote:

    Spot the stupid mistake...

    >template<size_t S>
    > struct CSpace_For<S, 2> { UInt16 m [(S+1)/2]; };
    >
    >template<size_t S>
    > struct CSpace_For<S, 4> { UInt32 m [(S+3)/4]; };
    >
    >template<size_t S>
    > struct CSpace_For<S, 8> { UInt64 m [(S+7)/8]; };


    Should be...

    template<size_t S>
    struct CSpace_For<S, 2> { UInt16 m [(S+1) & ~1]; };

    etc
    Stephen Horne, Sep 24, 2008
    #2
    1. Advertising

  3. Stephen Horne

    James Kanze Guest

    On Sep 24, 8:13 am, Stephen Horne <> wrote:
    > I understand that the next C++ standard will have features to
    > handle the alignment of data types. This is good, but a bit
    > late for me!


    > I've been using some template trickery to handle alignment
    > issues for some time. What I usually want is a type that takes
    > the same amount of space and has the same alignment as some
    > other type, but which doesn't have constructors, destructors
    > etc. The idea is that initialisation and cleanup can be done
    > with casts, placement new and explicit destructor calls, but
    > that this memory-only type can live in a union or whatever.


    > To get the alignment of an existing type, I use something
    > like...


    > template<typename T>
    > class CAlign_Of
    > {
    > private:
    > struct CDummy
    > {
    > char m_Char;
    > T m_T;
    > };


    > public:
    > enum { Align = ((size_t) &(((CDummy*) 0)->m_T)) };
    > };


    > Which I figure should be portable to any platform where char
    > is a single byte (though I don't think even that is
    > guaranteed).


    It is. By definition, char is a byte, and all other types
    consist of an integral number of bytes.

    > To create the replacement type, however, is a bit more of a
    > problem. To create a type the right size, you just use a
    > template struct containing and array of chars, but getting the
    > alignment right is the problem.


    > So...


    > 1. Is there a good portable solution now?
    > 2. What will the standard C++ solution be?
    > 3. How consistent are compilers in their non-standard alignment
    > handling right now? - e.g. does GCC c++ support an __alignof
    > extension similar to that on MS VC++?


    Technically, I don't think that there is a solution 100%
    guaranteed by the standard. Practically, I use the following:

    namespace GlobalPrivate {

    template< typename T, bool isSmaller >
    struct AlignTypeDetail ;

    template< typename T >
    struct AlignTypeDetail< T, false >
    {
    typedef T type ;
    } ;

    template< typename T >
    struct AlignTypeDetail< T, true >
    {
    typedef char type ;
    } ;

    template< typename T, typename U >
    struct AlignType
    {
    typedef typename AlignTypeDetail< U, (sizeof( T ) <
    sizeof( U )) >::type
    type ;
    } ;
    }

    template< typename T >
    union MaxAlignFor
    {
    typename GlobalPrivate::AlignType< T, char >::type c ;
    typename GlobalPrivate::AlignType< T, short >::type s ;
    typename GlobalPrivate::AlignType< T, int >::type i ;
    typename GlobalPrivate::AlignType< T, long >::type l ;
    typename GlobalPrivate::AlignType< T, long long >::type ll ;
    typename GlobalPrivate::AlignType< T, float >::type f ;
    typename GlobalPrivate::AlignType< T, double >::type d ;
    typename GlobalPrivate::AlignType< T, long double >::type ld ;
    typename GlobalPrivate::AlignType< T, void* >::type pc ;
    typename GlobalPrivate::AlignType< T, MaxAlign* >::type ps ;
    typename GlobalPrivate::AlignType< T, void (*)() >::type pf ;
    } ;

    and then declare a union:

    union
    {
    MaxAlignFor< T > dummyForAlignment ;
    unsigned char data[ sizeof( T ) ] ;
    } ;

    This supposes that 1) the required alignment will not be more
    than the alignment of one of the types in my MaxAlignFor union,
    and 2) it will not be more than the size of the type. The
    latter is more or less guaranteed by the standard (albeit very
    indirectly); the former seems safe for now, and if it does cause
    problems in the future, it shouldn't be any real problem to add
    another type to the MaxAlignFor union. (All such types must be
    POD, but I can't imagine that being a problem.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Sep 24, 2008
    #3
  4. I already posted one thankyou, but it didn't appear, so thankyou
    again.
    Stephen Horne, Sep 25, 2008
    #4
  5. Stephen Horne

    ma740988 Guest

    On Sep 24, 4:43 am, James Kanze <> wrote:
    > On Sep 24, 8:13 am, Stephen Horne <> wrote:
    >
    >
    >
    > > I understand that the next C++ standard will have features to
    > > handle thealignmentof data types. This is good, but a bit
    > > late for me!
    > > I've been using some template trickery to handlealignment
    > > issues for some time. What I usually want is a type that takes
    > > the same amount of space and has the samealignmentas some
    > > other type, but which doesn't have constructors, destructors
    > > etc. The idea is that initialisation and cleanup can be done
    > > with casts, placement new and explicit destructor calls, but
    > > that this memory-only type can live in a union or whatever.
    > > To get thealignmentof an existing type, I use something
    > > like...
    > > template<typename T>
    > > class CAlign_Of
    > > {
    > >   private:
    > >     struct CDummy
    > >     {
    > >      charm_Char;
    > >       T    m_T;
    > >     };
    > >   public:
    > >     enum { Align = ((size_t) &(((CDummy*) 0)->m_T)) };
    > > };
    > > Which I figure should be portable to any platform wherechar
    > > is a single byte (though I don't think even that is
    > > guaranteed).

    >
    > It is.  By definition,charis a byte, and all other types
    > consist of an integral number of bytes.
    >
    > > To create the replacement type, however, is a bit more of a
    > > problem.  To create a type the right size, you just use a
    > > template struct containing and array of chars, but getting the
    > >alignmentright is the problem.
    > > So...
    > > 1.  Is there a good portable solution now?
    > > 2.  What will the standard C++ solution be?
    > > 3.  How consistent are compilers in their non-standardalignment
    > >     handling right now? - e.g. does GCC c++ support an __alignof
    > >     extension similar to that on MS VC++?

    >
    > Technically, I don't think that there is a solution 100%
    > guaranteed by the standard.  Practically, I use the following:
    >
    >     namespace GlobalPrivate {
    >
    >     template< typename T, bool isSmaller >
    >     struct AlignTypeDetail ;
    >
    >     template< typename T >
    >     struct AlignTypeDetail< T, false >
    >     {
    >         typedef T type ;
    >     } ;
    >
    >     template< typename T >
    >     struct AlignTypeDetail< T, true >
    >     {
    >         typedefchartype ;
    >     } ;
    >
    >     template< typename T, typename U >
    >     struct AlignType
    >     {
    >         typedef typename AlignTypeDetail< U, (sizeof( T ) <
    > sizeof( U )) >::type
    >                             type ;
    >     } ;
    >     }
    >
    >     template< typename T >
    >     union MaxAlignFor
    >     {
    >         typename GlobalPrivate::AlignType< T,char>::type        c ;
    >         typename GlobalPrivate::AlignType< T, short >::type       s ;
    >         typename GlobalPrivate::AlignType< T, int >::type         i ;
    >         typename GlobalPrivate::AlignType< T, long >::type        l ;
    >         typename GlobalPrivate::AlignType< T, long long >::type   ll ;
    >         typename GlobalPrivate::AlignType< T, float >::type       f ;
    >         typename GlobalPrivate::AlignType< T,double>::type      d ;
    >         typename GlobalPrivate::AlignType< T, longdouble>::type ld ;
    >         typename GlobalPrivate::AlignType< T, void* >::type       pc ;
    >         typename GlobalPrivate::AlignType< T, MaxAlign* >::type   ps ;
    >         typename GlobalPrivate::AlignType< T, void (*)() >::type  pf ;
    >     } ;
    >
    > and then declare a union:
    >
    >     union
    >     {
    >         MaxAlignFor< T > dummyForAlignment ;
    >         unsignedchar   data[ sizeof( T ) ] ;
    >     } ;


    Pretty nifty solution here. When I try to compile this though I get
    the errors:

    1>c:\msvc_2007-orcas\dev\test\main.cpp(52) : error C2065: 'T' :
    undeclared identifier
    1>c:\msvc_2007-orcas\test\main.cpp(52) : error C2621: member '<unnamed-
    tag>::dummyForAlignment' of union '<unnamed-tag>' has copy constructor
    1>c:\msvc_2007-orcas\test\main.cpp(53) : error C2065: 'T' : undeclared
    identifier
    1>c:\msvc_2007-orcas\test\main.cpp(53) : error C2070: ''unknown-
    type'': illegal sizeof operand
    1>c:\msvc_2007-orcas\test\main.cpp(53) : warning C4200: nonstandard
    extension used : zero-sized array in struct/union

    where line 52 is the line 'MaxAlignFor< T > dummyForAlignment '. What
    am I doing wrong?
    Thanks
    ma740988, Oct 13, 2008
    #5
  6. Stephen Horne

    James Kanze Guest

    On Oct 13, 3:54 am, ma740988 <> wrote:
    > On Sep 24, 4:43 am, James Kanze <> wrote:
    > > On Sep 24, 8:13 am, Stephen Horne
    > > <> wrote:


    [...]
    > > Technically, I don't think that there is a solution 100%
    > > guaranteed by the standard. Practically, I use the following:


    > > namespace GlobalPrivate {


    > > template< typename T, bool isSmaller >
    > > struct AlignTypeDetail ;


    > > template< typename T >
    > > struct AlignTypeDetail< T, false >
    > > {
    > > typedef T type ;
    > > } ;


    > > template< typename T >
    > > struct AlignTypeDetail< T, true >
    > > {
    > > typedefchartype ;
    > > } ;


    > > template< typename T, typename U >
    > > struct AlignType
    > > {
    > > typedef typename AlignTypeDetail< U, (sizeof( T ) <
    > > sizeof( U )) >::type
    > > type ;
    > > } ;
    > > }


    > > template< typename T >
    > > union MaxAlignFor
    > > {
    > > typename GlobalPrivate::AlignType< T,char>::type c ;
    > > typename GlobalPrivate::AlignType< T, short >::type s ;
    > > typename GlobalPrivate::AlignType< T, int >::type i ;
    > > typename GlobalPrivate::AlignType< T, long >::type l ;
    > > typename GlobalPrivate::AlignType< T, long long >::type ll ;
    > > typename GlobalPrivate::AlignType< T, float >::type f ;
    > > typename GlobalPrivate::AlignType< T,double>::type d ;
    > > typename GlobalPrivate::AlignType< T, longdouble>::type ld ;
    > > typename GlobalPrivate::AlignType< T, void* >::type pc ;
    > > typename GlobalPrivate::AlignType< T, MaxAlign* >::type ps ;
    > > typename GlobalPrivate::AlignType< T, void (*)() >::type pf ;
    > > } ;


    > > and then declare a union:


    > > union
    > > {
    > > MaxAlignFor< T > dummyForAlignment ;
    > > unsignedchar data[ sizeof( T ) ] ;
    > > } ;


    > Pretty nifty solution here. When I try to compile this though
    > I get the errors:


    > 1>c:\msvc_2007-orcas\dev\test\main.cpp(52) : error C2065: 'T' :
    > undeclared identifier
    > 1>c:\msvc_2007-orcas\test\main.cpp(52) : error C2621: member '<unnamed-
    > tag>::dummyForAlignment' of union '<unnamed-tag>' has copy constructor
    > 1>c:\msvc_2007-orcas\test\main.cpp(53) : error C2065: 'T' : undeclared
    > identifier
    > 1>c:\msvc_2007-orcas\test\main.cpp(53) : error C2070: ''unknown-
    > type'': illegal sizeof operand
    > 1>c:\msvc_2007-orcas\test\main.cpp(53) : warning C4200: nonstandard
    > extension used : zero-sized array in struct/union


    > where line 52 is the line 'MaxAlignFor< T > dummyForAlignment
    > '. What am I doing wrong?


    What is T in the union? The error messages say you haven't
    defined it. There is a requirement here (although I didn't
    mention it) that the instantiation argument be a complete type;
    something like:

    class MyClass ;
    union
    {
    MaxAlignFor< MyClass > dummyForAlignment ;
    unsigned char data[ sizeof( MyClass ) ] ;
    } ;

    doesn't work.

    (The code above is copy/pasted from my actual headers, with the
    union copy/pasted from my current implementation of Fallible,
    and I compile it with g++, Sun CC and VC++ without problems.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Oct 13, 2008
    #6
  7. Stephen Horne

    Larry Evans Guest

    Larry Evans, Oct 27, 2008
    #7
  8. Chris M. Thomasson, Oct 28, 2008
    #8
  9. "ma740988" <> wrote in message
    news:...
    > On Sep 24, 4:43 am, James Kanze <> wrote:
    > > On Sep 24, 8:13 am, Stephen Horne <> wrote:
    > > > I understand that the next C++ standard will have features to
    > > > handle thealignmentof data types. This is good, but a bit
    > > > late for me!

    > [...]


    > Pretty nifty solution here.


    [...]

    Check this NASTY hack out:

    http://groups.google.com/group/comp.lang.c/msg/be7e0d0e97c5e1d9

    use the offsetof macro to attempt to determine max alignment. Here is a
    pre-alpha fairly crude C++ non-blocking region allocator which uses the
    hack:

    http://webpages.charter.net/appcore/vzoom/malloc/sergey_vzmem_thread.html

    here is some more context:

    http://groups.google.com/group/comp.programming.threads/browse_frm/thread/4038a7a8a4f5a7cb
    Chris M. Thomasson, Oct 28, 2008
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lionel B
    Replies:
    10
    Views:
    930
    Lionel B
    Jan 2, 2007
  2. mathemagic
    Replies:
    5
    Views:
    1,148
    Alan Johnson
    Feb 11, 2007
  3. Chris Thomasson
    Replies:
    2
    Views:
    313
    Chris Thomasson
    Mar 13, 2007
  4. structures and alignment issues

    , Jun 14, 2007, in forum: C Programming
    Replies:
    31
    Views:
    800
    Keith Thompson
    Jun 16, 2007
  5. Chris Thomasson

    allocator alignment issues...

    Chris Thomasson, Aug 22, 2007, in forum: C++
    Replies:
    1
    Views:
    360
    Chris Thomasson
    Aug 22, 2007
Loading...

Share This Page