Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   alignment issues (http://www.velocityreviews.com/forums/t636764-alignment-issues.html)

Stephen Horne 09-24-2008 06:13 AM

alignment issues
 
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 09-24-2008 06:17 AM

Re: alignment issues
 
On Wed, 24 Sep 2008 07:13:31 +0100, Stephen Horne
<sh006d3592@blueyonder.co.uk> 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


James Kanze 09-24-2008 08:43 AM

Re: alignment issues
 
On Sep 24, 8:13 am, Stephen Horne <sh006d3...@blueyonder.co.uk> 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:james.kanze@gmail.com
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

Stephen Horne 09-25-2008 03:34 PM

Re: alignment issues
 

I already posted one thankyou, but it didn't appear, so thankyou
again.


ma740988 10-13-2008 01:54 AM

Re: alignment issues
 
On Sep 24, 4:43*am, James Kanze <james.ka...@gmail.com> wrote:
> On Sep 24, 8:13 am, Stephen Horne <sh006d3...@blueyonder.co.uk> 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

James Kanze 10-13-2008 09:38 AM

Re: alignment issues
 
On Oct 13, 3:54 am, ma740988 <ma740...@gmail.com> wrote:
> On Sep 24, 4:43 am, James Kanze <james.ka...@gmail.com> wrote:
> > On Sep 24, 8:13 am, Stephen Horne
> > <sh006d3...@blueyonder.co.uk> 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:james.kanze@gmail.com
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

Larry Evans 10-27-2008 10:13 PM

Re: alignment issues
 
On 09/24/08 01:13, Stephen Horne wrote:
[snip]
> To get the alignment of an existing type, I use something like...

[snip]
Why not use boost's alignment_of:

http://www.boost.org/doc/libs/1_36_0...gnment_of.html

?

Chris M. Thomasson 10-28-2008 03:12 AM

Re: alignment issues
 
also, please check this crap out:

http://groups.google.com/group/comp....2bd4db8de1aad2

Wow! ;^D


Chris M. Thomasson 10-28-2008 03:12 AM

Re: alignment issues
 
"ma740988" <ma740988@gmail.com> wrote in message
news:e80fb452-c7e6-4a53-aac5-9ee00191a8ee@d31g2000hsg.googlegroups.com...
> On Sep 24, 4:43 am, James Kanze <james.ka...@gmail.com> wrote:
> > On Sep 24, 8:13 am, Stephen Horne <sh006d3...@blueyonder.co.uk> 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....7e0d0e97c5e1d9

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/...em_thread.html

here is some more context:

http://groups.google.com/group/comp....38a7a8a4f5a7cb



All times are GMT. The time now is 04:28 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.