Alignment Specifiers

0 views
Skip to first unread message

Tomás

unread,
May 31, 2006, 8:29:32 PM5/31/06
to

If we want a local object within a function, but want a different function
to initialise the object, we might try something like this:

#include <vector>

typedef unsigned char uchar;


/* The following functions use placement new internally */
std::vector<int> SomeFunc1(uchar*);
std::vector<int> SomeFunc2(uchar*);
std::vector<int> SomeFunc3(uchar*);
std::vector<int> SomeFunc4(uchar*);


#include <iostream>


int main()
{
uchar buffer[ sizeof( std::vector<int> ) ];


std::cout << "Choose method of initialisation: ";

unsigned choice; std::cin >> choice;


switch( choice )
{
case 1: SomeFunc1( buffer ); break;
case 2: SomeFunc2( buffer ); break;
case 3: SomeFunc3( buffer ); break;
case 4: SomeFunc4( buffer ); break;
}

/* Now work with the vector */

}


However, the problem with this is that "buffer" may not be aligned properly
to satisfy the alignment requirements of std::vector<int>. There's two
popular remedies:

(1) Dynamic allocation

uchar (&buffer)[ sizeof( std::vector<int> ) ] =
*new uchar[1][sizeof( std::vector<int> ) ];

This is guaranteed to be aligned adequately, but it's inefficient because
it uses dynamic memory allocation.

(2) Use a union

union StrictAlign {
long double a;
unsigned long b;
void *c;
};

StrictAlign sa[ sizeof(std::vector<int>) / sizeof(StrictAlign)
+ bool( sizeof(std::vector<int>) % sizeof(StrictAlign)
) ];

uchar (&buffer)[ sizeof( std::vector<int> ) ]
= reinterpret_cast<uchar (&)[sizeof( std::vector<int> )]>(sa);


This is fairly efficient, but it isn't guaranteed to work.

It would be nice to be able to specify alignment requirements for an array
of char's, possibly by extending the functionality of one of the following
keywords:


uchar buffer[ sizeof(std::vector<int>) ] virtual std::vector<int>;

uchar buffer[ sizeof(std::vector<int>) ] for std::vector<int>;

uchar buffer[ sizeof(std::vector<int>) ] explicit std::vector<int>;

-Tomás

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

SuperKoko

unread,
Jun 1, 2006, 11:34:55 AM6/1/06
to

Tomás wrote:
> It would be nice to be able to specify alignment requirements for an array
> of char's, possibly by extending the functionality of one of the following
> keywords:
>
>
> uchar buffer[ sizeof(std::vector<int>) ] virtual std::vector<int>;
>
> uchar buffer[ sizeof(std::vector<int>) ] for std::vector<int>;
>
> uchar buffer[ sizeof(std::vector<int>) ] explicit std::vector<int>;
>
I think that a more basic feature (extremely simple to implement for
compilers), would be to provide an alignmentof<type>() template.
It would return the minimum alignment requirement of the type.
There would also be a universal_alignmentof constant which would
require an alignment large enough for all types (the same alignment
than malloc uses internally).

If you want a simple-to-implement and simple-to-understand feature that
will allow to efficiently uses aligned memory (anywhere : automatic
variables, static-storage variables, member variables), it would be
possible to add alignment as a type qualifier.
Like that:

typedef declalign(4) int
int_which_is_deemed_as_having_a_4_bytes_alignment_requirement;

It would mainly obey to the cv-qualifiers rules.

I think that it is easy to implement for compilers who already treat
alignment requirements of structures, because they already bind
internally an alignement requirement to each structure.

It would be possible to allow implementation which don't support
alignment requirements (for instance on platforms wich don't require
them) to simply ignore such type qualifiers.

It means that it should only be used to avoid UB when constructing
objects on this memory space.

Howard Hinnant

unread,
Jun 2, 2006, 11:57:17 AM6/2/06
to
In article <1149166816....@c74g2000cwc.googlegroups.com>,
"SuperKoko" <tabk...@yahoo.fr> wrote:

> Tomás wrote:
> > It would be nice to be able to specify alignment requirements for an array
> > of char's, possibly by extending the functionality of one of the following
> > keywords:
> >
> >
> > uchar buffer[ sizeof(std::vector<int>) ] virtual std::vector<int>;
> >
> > uchar buffer[ sizeof(std::vector<int>) ] for std::vector<int>;
> >
> > uchar buffer[ sizeof(std::vector<int>) ] explicit std::vector<int>;
> >
> I think that a more basic feature (extremely simple to implement for
> compilers), would be to provide an alignmentof<type>() template.
> It would return the minimum alignment requirement of the type.
> There would also be a universal_alignmentof constant which would
> require an alignment large enough for all types (the same alignment
> than malloc uses internally).
>
> If you want a simple-to-implement and simple-to-understand feature that
> will allow to efficiently uses aligned memory (anywhere : automatic
> variables, static-storage variables, member variables), it would be
> possible to add alignment as a type qualifier.
> Like that:
>
> typedef declalign(4) int
> int_which_is_deemed_as_having_a_4_bytes_alignment_requirement;
>
> It would mainly obey to the cv-qualifiers rules.

The C++0X working draft currently has:

std::aligned_storage
<
sizeof(std::vector<int>),
std::alignment_of<std::vector<int>>::value
>::type buffer;

It may already be shipping on your platform except under namespace
std::tr1. The header to access it is <type_traits>. You can also find
this functionality at boost.

There are some use cases where the type you are aligning for is not
known at the time you declare the buffer. For that reason I am trying
to get the second parameter of aligned_storage defaulted such that if
you don't specify it, you'll get the "most stringent alignment
requirement" as currently specified in 5.3.4p10. Then you could also
say:

std::aligned_storage<buffer_size>::type buffer;

The resulting alignment would then be sufficient, and perhaps overly so
(as in new/malloc).

-Howard

frege

unread,
Jun 6, 2006, 1:02:28 AM6/6/06
to

Howard Hinnant wrote:
> The C++0X working draft currently has:
>
> std::aligned_storage
> <
> sizeof(std::vector<int>),
> std::alignment_of<std::vector<int>>::value
> >::type buffer;
>
> It may already be shipping on your platform except under namespace
> std::tr1. The header to access it is <type_traits>. You can also find
> this functionality at boost.
>

I'd like this wrapped into 'storage_for' or something like that. As
in:

std::storage_for<std::vector<int>>::type buffer;

which I could make from aligned_storage, but my version wouldn't be in
std::!

> There are some use cases where the type you are aligning for is not
> known at the time you declare the buffer. For that reason I am trying
> to get the second parameter of aligned_storage defaulted such that if
> you don't specify it, you'll get the "most stringent alignment
> requirement" as currently specified in 5.3.4p10. Then you could also
> say:
>
> std::aligned_storage<buffer_size>::type buffer;
>
> The resulting alignment would then be sufficient, and perhaps overly so
> (as in new/malloc).

That would be perfect. I was writing something literally a few hours
ago that needs that.

>
> -Howard
>

Tony

frege

unread,
Jun 13, 2006, 2:43:36 PM6/13/06
to

Howard Hinnant wrote:
>
> The C++0X working draft currently has:
>
> std::aligned_storage
> <
> sizeof(std::vector<int>),
> std::alignment_of<std::vector<int>>::value
> >::type buffer;
>
>
> There are some use cases where the type you are aligning for is not
> known at the time you declare the buffer. For that reason I am trying
> to get the second parameter of aligned_storage defaulted such that if
> you don't specify it, you'll get the "most stringent alignment
> requirement" as currently specified in 5.3.4p10. Then you could also
> say:
>
> std::aligned_storage<buffer_size>::type buffer;
>
> The resulting alignment would then be sufficient, and perhaps overly so
> (as in new/malloc).
>
> -Howard
>

I notice that the boost version works such that if alignment isn't
specified, it defaults to size_t(-1) and, eventually, max_align. I
would think, however, that you could align to smaller than max_align
when buffer_size is less than max_align. ie if buffer_size is 1, then
alignment of 1 should be good enough. Even if buffer_size is, say, 7,
the required alignment is at most 4 (as an example on a typical
machine). I think this should be possible, in boost's version at
least, with, at most, a complicated series of mpl::if's.

Tony

Howard Hinnant

unread,
Jun 13, 2006, 4:24:45 PM6/13/06
to
In article <1150219241.9...@i40g2000cwc.googlegroups.com>,
"frege" <gottlo...@gmail.com> wrote:

Yes. The definition in 5.3.4p10 allows for this.

> ... shall be an integral multiple of the most stringent
> alignment requirement (basic.types) of any object type
> whose size is no greater than the size of the array being
> created.

In my own implementation aligned_storage<5>::type has alignment and
sizeof 8, though there exists objects on this platform which require
alignment of 16. alignment of 4, sizeof 8 is an interesting answer. If
I get some spare time, I may change to that.

Keep in mind that one must be able to create arrays of
aligned_storage<5>::type, and that both the first and second elements in
the array must meet the alignment requirement (thus the need to pad the
sizeof if alignment is greater than 1).

-Howard

Reply all
Reply to author
Forward
0 new messages