Alignment

B

better_cs_now

Hello All,

Please consider the two definitions below:

Foo foo;
unsigned char foo[sizeof(Foo)];

Are these guaranteed to have the same alignment, or will the second
definition have an alignment that is only modulo 1?

Thanks,
Dave
 
G

Gert-Jan de Vos

Foo foo;
unsigned char foo[sizeof(Foo)];

Are these guaranteed to have the same alignment, or will the second
definition have an alignment that is only modulo 1?

The standard has the answer in 3.1-5 [basic.types]:

"Object types have alignment requirements (3.9.1, 3.9.2). The
alignment of a complete object type is an implementation-defined
integer value representing a number of bytes; an object is allocated
at an address that meets the alignment requirements of its object
type."

So, unless your Foo is a typedef for an array of unsigned char, then
your foo objects are two different types. Therefore both have their
own implementation-defined alignment en you can not portably assume
they will be the same.
 
B

better_cs_now

Foo foo;
unsigned char foo[sizeof(Foo)];
Are these guaranteed to have the same alignment, or will the second
definition have an alignment that is only modulo 1?

The standard has the answer in 3.1-5 [basic.types]:

"Object types have alignment requirements (3.9.1, 3.9.2). The
alignment of a complete object type is an implementation-defined
integer value representing a number of bytes; an object is allocated
at an address that meets the alignment requirements of its object
type."

So, unless your Foo is a typedef for an array of unsigned char, then
your foo objects are two different types. Therefore both have their
own implementation-defined alignment en you can not portably assume
they will be the same.

To force the unsigned char array to have the same alignment as the Foo
(which is my goal), I'd like to put these together in a union.
However, Foo has a non-trivial constructor, so it may not be a member
of a union. Do I have any othre options?

Thanks to all!
 
P

peter koch

Foo foo;
unsigned char foo[sizeof(Foo)];
Are these guaranteed to have the same alignment, or will the second
definition have an alignment that is only modulo 1?
The standard has the answer in 3.1-5 [basic.types]:
"Object types have alignment requirements (3.9.1, 3.9.2). The
alignment of a complete object type is an implementation-defined
integer value representing a number of bytes; an object is allocated
at an address that meets the alignment requirements of its object
type."
So, unless your Foo is a typedef for an array of unsigned char, then
your foo objects are two different types. Therefore both have their
own implementation-defined alignment en you can not portably assume
they will be the same.

To force the unsigned char array to have the same alignment as the Foo
(which is my goal), I'd like to put these together in a union.
However, Foo has a non-trivial constructor, so it may not be a member
of a union. Do I have any othre options?

Yes. Search this group and the moderated one for a solution that will
give the correct alignment (basically: a union containing all possible
types and the char representation).

/Peter
 
G

Greg Herlihy

On Feb 26, 11:18 am, Gert-Jan de Vos <gert-

To force the unsigned char array to have the same alignment as the Foo
(which is my goal), I'd like to put these together in a union.
However, Foo has a non-trivial constructor, so it may not be a member
of a union. Do I have any othre options?

Allocate the char array dynamically:

char * fooArray = new char[sizeof(Foo)];

Now fooArray will be suitably aligned for a Foo type.

Greg
 
B

better_cs_now

On Feb 26, 11:18 am, Gert-Jan de Vos <gert-
To force the unsigned char array to have the same alignment as the Foo
(which is my goal), I'd like to put these together in a union.
However, Foo has a non-trivial constructor, so it may not be a member
of a union. Do I have any othre options?

Allocate the char array dynamically:

   char * fooArray = new char[sizeof(Foo)];

Now fooArray will be suitably aligned for a Foo type.

Greg

Unfortunately, allocating on the heap is verboten in our application.
Whether it makes sense or not, it is what it is and it will not pass
the design review.

The memory I'm trying to get properly aligned is actually going to be
static in a class and will have a singleton instance of the class
constructed in it via placement new.

class Foo
{
...
static unsigned char s_pInstance[];
};

unsigned char Foo::s_pInstance[sizeof(Foo)]; // Will have a Foo
constructed in it

The goal is to ensure that s_pInstance is suitably aligned to hold a
Foo. Is this possible within the bounds of the C++ language standard,
or is it an architecture issue (in which case I'm in the wrong group)?
 
B

better_cs_now

On Feb 26, 11:18 am, Gert-Jan de Vos <gert-
To force the unsigned char array to have the same alignment as the Foo
(which is my goal), I'd like to put these together in a union.
However, Foo has a non-trivial constructor, so it may not be a member
of a union. Do I have any othre options?

Allocate the char array dynamically:

   char * fooArray = new char[sizeof(Foo)];

Now fooArray will be suitably aligned for a Foo type.

Greg

In addition to my prvious response a minute ago, your comment brings
up a side issue.

In my original post, I showed the Foo and the char array being
constructed off of the heap, and the response was that the alignment I
seek is not guaranteed. However, your response clearly states that the
alignment I seek *will* be guaranteed if they are constructed on the
heap. So, I'd like to reconfirm -- are alignment issues indeed treated
differently on the heap than off?

Thanks for the response!
 
B

Bo Persson

On Feb 26, 11:18 am, Gert-Jan de Vos <gert-
To force the unsigned char array to have the same alignment as
the Foo (which is my goal), I'd like to put these together in a
union. However, Foo has a non-trivial constructor, so it may not
be a member of a union. Do I have any othre options?

Allocate the char array dynamically:

char * fooArray = new char[sizeof(Foo)];

Now fooArray will be suitably aligned for a Foo type.

Greg

In addition to my prvious response a minute ago, your comment brings
up a side issue.

In my original post, I showed the Foo and the char array being
constructed off of the heap, and the response was that the
alignment I seek is not guaranteed. However, your response clearly
states that the alignment I seek *will* be guaranteed if they are
constructed on the heap. So, I'd like to reconfirm -- are alignment
issues indeed treated differently on the heap than off?

Thanks for the response!

No, the "trick" is the use of the global operator new,

void* operator new(std::size_t size) throw(std::bad_alloc);

which is required to allocate bytes "suitably aligned to represent any
object of that size".

Note that the operator doesn't know the type of the object, but must
still obey the rule. We don't know how!


Bo Persson
 
G

Gert-Jan de Vos

Allocate the char array dynamically:
   char * fooArray = new char[sizeof(Foo)];
Now fooArray will be suitably aligned for a Foo type.

In addition to my previous response a minute ago, your comment brings
up a side issue.

In my original post, I showed the Foo and the char array being
constructed off of the heap, and the response was that the alignment I
seek is not guaranteed. However, your response clearly states that the
alignment I seek *will* be guaranteed if they are constructed on the
heap. So, I'd like to reconfirm -- are alignment issues indeed treated
differently on the heap than off?

If you are after a singleton implementation that doesn't use the heap,
why not use Meyers singleton?

The standard specifically states that new array of char or unsigned
char provides correct alignment for any object that fits in the
requested size. This explicitly allows what you are after, except that
it needs heap storage.
 
B

better_cs_now

Allocate the char array dynamically:
   char * fooArray = new char[sizeof(Foo)];
Now fooArray will be suitably aligned for a Foo type.
Greg
In addition to my previous response a minute ago, your comment brings
up a side issue.
In my original post, I showed the Foo and the char array being
constructed off of the heap, and the response was that the alignment I
seek is not guaranteed. However, your response clearly states that the
alignment I seek *will* be guaranteed if they are constructed on the
heap. So, I'd like to reconfirm -- are alignment issues indeed treated
differently on the heap than off?

If you are after a singleton implementation that doesn't use the heap,
why not use Meyers singleton?

The standard specifically states that new array of char or unsigned
char provides correct alignment for any object that fits in the
requested size. This explicitly allows what you are after, except that
it needs heap storage.- Hide quoted text -

- Show quoted text -

I had started with the Meyers singleton, but the problem I quickly ran
into was losing control over the sequence in which my singletons are
destructed. I have a lot of singletons, and there are dependencies
among them. So I must maintain control over their destruction order.
Having them constructed as static objects (i.e. as Meyers singletons)
deprives me of that control.
 
C

Chris M. Thomasson

Hello All,

Please consider the two definitions below:

Foo foo;
unsigned char foo[sizeof(Foo)];

Are these guaranteed to have the same alignment, or will the second
definition have an alignment that is only modulo 1?

You can attempt to calculate alignment of `Foo' objects like this:
___________________________________________________________________
#include <cstddef>
#include <cstdio>


struct Foo {
char a;
int b;
double c;

Foo(int b) {
// [...];
}
};


template<typename T>
size_t get_type_alignment() {
struct aligner {
char m_pad;
T m_obj;
};
return offsetof(aligner, m_obj);
}


int main() {
std::printf("%lu\n", (unsigned long)get_type_alignment<Foo>());


//--------------------------------------------------------------
std::puts("\n\n\n____________________________________________"
"____\npress <ENTER> to exit...");
std::fflush(stdin);
std::fflush(stdout);
std::getchar();
return 0;
}
___________________________________________________________________




Also, perhaps the following code will help you:

http://groups.google.com/group/comp.lang.c++/browse_frm/thread/f62bd4db8de1aad2
(read all...)
 
C

Chris M. Thomasson

This should do what you want:
____________________________________________________________________
#include <cstddef>
#include <cstdio>
#include <new>


struct Foo {
int b;
char a;
double c;

Foo(int b) {
// [...];
}
};


#define ALIGN_POW2(mp_this, mp_type) ((mp_type)( \
(((std::ptrdiff_t)(mp_this)) + 1) & (-2) \
))


#define ALIGN(mp_this, mp_type, mp_align) ((mp_type)( \
(((std::ptrdiff_t)(mp_this)) + \
ALIGN_POW2(mp_align, std::ptrdiff_t) - 1) \
& (-ALIGN_POW2(mp_align, std::ptrdiff_t)) \
))


template<typename T, std::size_t CUSTOM_ALIGN = 0>
struct alignment {
struct aligner {
char m_pad;
T m_obj;
};

enum constant {
ALIGN_SIZE = (! CUSTOM_ALIGN) ? offsetof(aligner, m_obj) :
CUSTOM_ALIGN
};

template<typename T1>
static T1* align_ptr(void* ptr) {
return ALIGN(ptr, T1, ALIGN_SIZE);
}

class buffer {
enum constant {
REAL_SIZE = sizeof(T) + ALIGN_SIZE - 1
};

unsigned char m_raw[REAL_SIZE];
unsigned char* const m_align;

public:
buffer() : m_align(ALIGN(m_raw, unsigned char*, ALIGN_SIZE)) {
std::printf("buffer size: %lu\n", (unsigned long)REAL_SIZE);
std::printf("raw buffer: %p\n", (void*)m_raw);
std::printf("align buffer: %p\n", (void*)m_align);
}

unsigned char* get() const {
return m_align;
}
};
};


int main() {
alignment<Foo>::buffer buffer1;

Foo* foo = new (buffer1.get()) Foo(123);

foo->~Foo();

// 1024 byte buffer aligned on a 128 byte boundary...
alignment<unsigned char[1024], 128>::buffer buffer2;


//--------------------------------------------------------------
std::puts("\n\n\n____________________________________________"
"____\npress <ENTER> to exit...");
std::fflush(stdin);
std::fflush(stdout);
std::getchar();
return 0;
}
____________________________________________________________________




Any thoughts?
 
J

James Kanze

On 26 Feb., 19:36, (e-mail address removed) wrote:

[...]
Yes. Search this group and the moderated one for a solution
that will give the correct alignment (basically: a union
containing all possible types and the char representation).

I'm pretty sure you know this, but for precision's sake: the set
of all possible types is infinite, which means that you're going
to have to compromize some. Generally speaking, the set of all
basic types, plus a couple of different types of pointers
(void*, int*, struct X*, a pointer to a function, maybe pointers
to different types of members) should largely suffice. (It
would fail, of course, if in the implementation, the size of a
pointer depends on a hash code of the canonical type of the
pointed to object. Which is, I think, legal, but not something
I'd worry about encountering. It might change if the compiler
ensures some sort of special alignment for arrays, in order to
use some special hardware.)

In practice, this may result in a larger array than necessary if
the other type is small, e.g.:

struct Foo { char a[2] ; } ;

union {
unsigned char data[ sizeof( Foo ) ] ;
MaxAlignment dummyForAlignment ;
} ;

(where MaxAlignment is a union of all of the types). To avoid
this, you can do something like:

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 AlignType< T, char >::type c ;
typename AlignType< T, short >::type s ;
typename AlignType< T, int >::type i ;
typename AlignType< T, long >::type l ;
typename AlignType< T, long long >::type ll ;
typename AlignType< T, float >::type f ;
typename AlignType< T, double >::type d ;
typename AlignType< T, long double >::type ld ;
typename AlignType< T, void* >::type pc ;
typename AlignType< T, MaxAlign* >::type ps ;
typename AlignType< T, void (*)() >::type pf ;
// (I've yet to find a machine where I've needed
// more than the above.)
} ;

Since the required alignment for Foo can never be more than
sizeof(Foo), this only puts types whose size is less than or
equal to the size of Foo in the union.
 
J

James Kanze

Please consider the two definitions below:
Foo foo;
unsigned char foo[sizeof(Foo)];
Are these guaranteed to have the same alignment, or will the
second definition have an alignment that is only modulo 1?
You can attempt to calculate alignment of `Foo' objects like this:

Which isn't what he needs, but...
___________________________________________________________________
#include <cstddef>
#include <cstdio>
struct Foo {
char a;
int b;
double c;
Foo(int b) {
// [...];
}
};
template<typename T>
size_t get_type_alignment() {
struct aligner {
char m_pad;
T m_obj;
};
return offsetof(aligner, m_obj);

This is undefined behavior if T isn't a POD (and Foo isn't). It
won't compile with at least one compiler I use.
 
C

Chris M. Thomasson

Please consider the two definitions below:
Foo foo;
unsigned char foo[sizeof(Foo)];
Are these guaranteed to have the same alignment, or will the
second definition have an alignment that is only modulo 1?
You can attempt to calculate alignment of `Foo' objects like this:
Which isn't what he needs, but...
___________________________________________________________________
#include <cstddef>
#include <cstdio>
struct Foo {
char a;
int b;
double c;
Foo(int b) {
// [...];
}
};
template<typename T>
size_t get_type_alignment() {
struct aligner {
char m_pad;
T m_obj;
};
return offsetof(aligner, m_obj);
This is undefined behavior if T isn't a POD (and Foo isn't). It
won't compile with at least one compiler I use.

DOH!!! Yes, of course! My mistake. Thanks!




What about something like the following hack James?:
______________________________________________________________________
#include <cstddef>
#include <cstdio>
#include <climits>
#include <new>




template<typename T, std::size_t CUSTOM_ALIGN = 0U>
class alignment {
struct aligner_1 {
T m_obj;
};

struct aligner_2 {
char m_pad;
aligner_1 m_obj;
};


public:
enum constant {
ALIGN_SIZE = (! CUSTOM_ALIGN)
? sizeof(aligner_2) - sizeof(aligner_1)
: CUSTOM_ALIGN,
BUFFER_SIZE = sizeof(aligner_1) + (size_t)ALIGN_SIZE - 1U
};

static void* align_ptr(void* ptr) {
return ALIGN_SIZE > 1
? (void*)((((size_t)ptr) + ((size_t)ALIGN_SIZE - 1U))
& ~((size_t)ALIGN_SIZE - 1U))
: ptr;
}


private:
typedef char sassert[
ALIGN_SIZE > 0 &&
BUFFER_SIZE > 0 &&
ALIGN_SIZE <= INT_MAX &&
BUFFER_SIZE <= INT_MAX &&
ALIGN_SIZE > 1 ? ! ((size_t)ALIGN_SIZE % 2U) : 1 &&
sizeof(std::size_t) == sizeof(void*) ? 1 : -1
];
};




struct Base {
char x;
virtual void foo() = 0;
};


struct Foo : Base {
char a[5];
int b[3];
double c[2];

Foo(int x) {
// [...];
}

void foo() {

}
};




int main() {
std::printf(
"alignment of Foo: %lu\n"
"alignment of Foo*: %lu\n"
"alignment of Foo&: %lu\n",
(unsigned long)alignment<Foo>::ALIGN_SIZE,
(unsigned long)alignment<Foo*>::ALIGN_SIZE,
(unsigned long)alignment<Foo&>::ALIGN_SIZE
);

unsigned char foo_raw_buffer[
alignment<Foo>::BUFFER_SIZE
];

Foo* f = new (alignment<Foo>::align_ptr(foo_raw_buffer)) Foo(123);

std::printf(
"\nfoo_raw_buffer: %p\n"
"foo_raw_buffer_size: %lu\n"
"foo_align_buffer: %p\n",
(void*)foo_raw_buffer,
(unsigned long)alignment<Foo>::BUFFER_SIZE,
(void*)f
);

f->~Foo();

unsigned char page_raw_buffer[
alignment<unsigned char[8192], 8192>::BUFFER_SIZE
];

void* page_align_buffer =
alignment<unsigned char[8192], 8192>::align_ptr(page_raw_buffer);

std::printf(
"\npage_raw_buffer: %p\n"
"page_raw_buffer_size: %lu\n"
"page_align_buffer: %p\n",
(void*)page_raw_buffer,
(unsigned long)alignment<unsigned char[8192], 8192>::BUFFER_SIZE,
page_align_buffer
);

std::printf(
"\nalignment of char: %lu\n"
"alignment of short: %lu\n"
"alignment of int: %lu\n"
"alignment of long: %lu\n"
"alignment of float: %lu\n"
"alignment of double: %lu\n",
(unsigned long)alignment<char>::ALIGN_SIZE,
(unsigned long)alignment<short>::ALIGN_SIZE,
(unsigned long)alignment<int>::ALIGN_SIZE,
(unsigned long)alignment<long>::ALIGN_SIZE,
(unsigned long)alignment<float>::ALIGN_SIZE,
(unsigned long)alignment<double>::ALIGN_SIZE
);




//--------------------------------------------------------------
std::puts("\n\n\n____________________________________________"
"____\npress <ENTER> to exit...");
std::fflush(stdin);
std::fflush(stdout);
std::getchar();
return 0;
}
______________________________________________________________________




Does that compile on all your compilers? Odd that the broken code which used
`offsetof' macro on non-POD type compiles file on Comeau without warning. Oh
well, shi% happens.


How can I improve this hack?



;^(...
 
C

Chris M. Thomasson

blargg said:

You make good points blargg. The hack was busted.

[...]
Perhaps you could eliminate this by using the size of aligner less the
size of T. Putting it all together into a simplified class:

#include <iostream>
#include <cstddef>
using namespace std;

template<typename T>
class alignment {
struct align_t {
char pad;
T obj;
};
public:
// Alignment requirement of T
enum { n = sizeof (align_t) - sizeof (T) };

// Size of buffer needed when its alignment is unknown
enum { buf = sizeof (align_t) - 1 };
};

Well, what if T is a reference type? Should that not be something like:



template<typename T>
class alignment {
struct align_1_t {
T obj;
};

struct align_2_t {
char pad;
align_1_t obj;
};

public:
// Alignment requirement of T
enum { n = sizeof (align_2_t) - sizeof (align_1_t) };

// Size of buffer needed when its alignment is unknown
enum { buf = sizeof (align_1_t) + n - 1 };
};



What am I missing here?
 
J

James Kanze

"James Kanze" <[email protected]> wrote in message
On Feb 27, 4:15 am, "Chris M. Thomasson" <[email protected]>
wrote:
Please consider the two definitions below:
Foo foo;
unsigned char foo[sizeof(Foo)];
Are these guaranteed to have the same alignment, or will the
second definition have an alignment that is only modulo 1?
You can attempt to calculate alignment of `Foo' objects like this:
Which isn't what he needs, but...
___________________________________________________________________
#include <cstddef>
#include <cstdio>
struct Foo {
char a;
int b;
double c;
Foo(int b) {
// [...];
}
};
template<typename T>
size_t get_type_alignment() {
struct aligner {
char m_pad;
T m_obj;
};
return offsetof(aligner, m_obj);
This is undefined behavior if T isn't a POD (and Foo isn't). It
won't compile with at least one compiler I use.
DOH!!! Yes, of course! My mistake. Thanks!

What about something like the following hack James?:
______________________________________________________________________
#include <cstddef>
#include <cstdio>
#include <climits>
#include <new>
template<typename T, std::size_t CUSTOM_ALIGN = 0U>
class alignment {
struct aligner_1 {
T m_obj;
};
struct aligner_2 {
char m_pad;
aligner_1 m_obj;
};
public:
enum constant {
ALIGN_SIZE = (! CUSTOM_ALIGN)
? sizeof(aligner_2) - sizeof(aligner_1)
: CUSTOM_ALIGN,
BUFFER_SIZE = sizeof(aligner_1) + (size_t)ALIGN_SIZE - 1U
};
static void* align_ptr(void* ptr) {
return ALIGN_SIZE > 1
? (void*)((((size_t)ptr) + ((size_t)ALIGN_SIZE - 1U))
& ~((size_t)ALIGN_SIZE - 1U))
: ptr;
}
private:
typedef char sassert[
ALIGN_SIZE > 0 &&
BUFFER_SIZE > 0 &&
ALIGN_SIZE <= INT_MAX &&
BUFFER_SIZE <= INT_MAX &&
ALIGN_SIZE > 1 ? ! ((size_t)ALIGN_SIZE % 2U) : 1 &&
sizeof(std::size_t) == sizeof(void*) ? 1 : -1
];
};

My basic question is why? It doesn't enforce the alignment of
the buffer; it allocates a slightly larger buffer, and then
determines the first aligned address in it. A solution using a
union will force the compiler to align correctly to begin with.

[...]
Does that compile on all your compilers?
Probably.

Odd that the broken code which used `offsetof' macro on
non-POD type compiles file on Comeau without warning.

It's more or less a library issue. G++ can detect the problem
because offsetof is defined as something like:
#define offsetof( a, b ) __buildin_offsetof( a, b )
and handled by the compiler. The library you're using with
Comeau probably exploits some other undefined behavior; the
classical implementation is something like:
#define offsetof( a, b ) ((size_t)(&((a*)0)->b))
This dereferences a null pointer, but in a way such that most
compilers won't actually generate any code for it. So it never
causes a compiler error, nor a core dump (but in some cases
where virtual bases are involved, it might give a wrong answer).
 
C

Chris M. Thomasson

[...]
What about something like the following hack James?:
______________________________________________________________________
My basic question is why? It doesn't enforce the alignment of
the buffer; it allocates a slightly larger buffer, and then
determines the first aligned address in it. A solution using a
union will force the compiler to align correctly to begin with.

How can I use a union to align an arbitrary object up to, say, a 8192 byte
boundary? I can do this using the posted hack like:
_______________________________________________________________________
void foo() {
unsigned char page_raw_buffer[
alignment<unsigned char[8192], 8192>::BUFFER_SIZE
];

void* page_align_buffer =
alignment<unsigned char[8192], 8192>::align_ptr(page_raw_buffer);
}
_______________________________________________________________________




What am I missing?
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top