Velocity Reviews > Alignment problems

# Alignment problems

jacob navia
Guest
Posts: n/a

 07-08-2010
One of the critics to the container library was that I did not align in
the sample implementation the values given to it as the element size. In
some machines, accessing double data in an unaligned fashion could
provoke a segmentation fault.

My answer was that any actual implementation could take care
specifically of any alignment problems but in retrospect that is making
things too easy for me. So I have added the following macros to align
data when requesting an element size:

#define roundupTo(x,n) (((x)+((n)-1))&(~((n)-1)))
#define roundup(x) roundupTo(x,sizeof(void *))

The first macro supposes that sizeof(void *) is a power of two. Besides
the DeathStar 9000 has anyone ever heared from a machine where
sizeof(void *) is NOT a power of two?

The second macro supposes that all alignment problems disappear if we
align to sizeof void *. Has anyone here an example where that is not true?

Jacob

Ian Collins
Guest
Posts: n/a

 07-08-2010
On 07/ 8/10 08:59 PM, jacob navia wrote:
> One of the critics to the container library was that I did not align in
> the sample implementation the values given to it as the element size. In
> some machines, accessing double data in an unaligned fashion could
> provoke a segmentation fault.
>
> My answer was that any actual implementation could take care
> specifically of any alignment problems but in retrospect that is making
> things too easy for me. So I have added the following macros to align
> data when requesting an element size:
>
> #define roundupTo(x,n) (((x)+((n)-1))&(~((n)-1)))
> #define roundup(x) roundupTo(x,sizeof(void *))

Why don't you use inline functions?

> The first macro supposes that sizeof(void *) is a power of two. Besides
> the DeathStar 9000 has anyone ever heared from a machine where
> sizeof(void *) is NOT a power of two?
>
> The second macro supposes that all alignment problems disappear if we
> align to sizeof void *. Has anyone here an example where that is not true?

double and long double may be an issue, especially on a 32 bit machine.

const size_t shift = (sizeof(long double)/sizeof(void*)-1);

size_t roundup( size_t x )
{
return roundupTo( x, sizeof(void*)<<shift );
}

--
Ian Collins

jacob navia
Guest
Posts: n/a

 07-08-2010
Ian Collins a écrit :

> Why don't you use inline functions?
>

Because microsoft refuses to accept "inline" in their compilers and the
library must be compatible with microsoft windows.

>
> double and long double may be an issue, especially on a 32 bit machine.
>
>
> const size_t shift = (sizeof(long double)/sizeof(void*)-1);
>

In a 32 bit machine sizeof(long double) can be 12 (lcc-win for instance)
and sizeof (void *) is 4. 12/4 --> 3, minus one is 2. Shift is two.

> size_t roundup( size_t x )
> {
> return roundupTo( x, sizeof(void*)<<shift );
> }
>

That sizeof(void *) * 2 is 8. We would round up to 8 when only 4 is
necessary... at least in the x86 architecture.

Ian Collins
Guest
Posts: n/a

 07-08-2010
On 07/ 8/10 09:52 PM, jacob navia wrote:
> Ian Collins a écrit :
>
>> Why don't you use inline functions?
>>

>
> Because microsoft refuses to accept "inline" in their compilers and the
> library must be compatible with microsoft windows.

Blimey.

>> double and long double may be an issue, especially on a 32 bit machine.
>>
>>
>> const size_t shift = (sizeof(long double)/sizeof(void*)-1);
>>

>
> In a 32 bit machine sizeof(long double) can be 12 (lcc-win for instance)
> and sizeof (void *) is 4. 12/4 --> 3, minus one is 2. Shift is two.

So the alignment will be 16, which should be safe for any long double.

>> size_t roundup( size_t x )
>> {
>> return roundupTo( x, sizeof(void*)<<shift );
>> }
>>

>
> That sizeof(void *) * 2 is 8. We would round up to 8 when only 4 is
> necessary... at least in the x86 architecture.

* 4, rounding to 16. I was being conservative!

--
Ian Collins

Keith Thompson
Guest
Posts: n/a

 07-08-2010
jacob navia <(E-Mail Removed)> writes:
[...]
> The second macro supposes that all alignment problems disappear if we
> align to sizeof void *. Has anyone here an example where that is not true?

I've used several systems where long double, or even double, has
stricter alignment requirements than void* (e.g., void* requires
4-byte alignment and long double requires 8-byte aligbment).

Actually I'm not certain that the stricter alignment is *required* in
all cases; I have a test program that infers alignment requirements
from how struct members are allocated, but compilers can impose
stricter alignment than is necessary.

Function pointers are probably also worth checking. I seem to
recall that on the AS/400 function pointers are much larger than
data pointers, but I don't know about alignment requirements.

If you take the maximum required alignment of any of:
long long
intmax_t
double
long double
void*
void(*)(void)
you're very likely to be ok. (I wouldn't skip anything from this
list; for example, if long double is implemented in software,
it might be less strictly aligned than double.)

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Seebs
Guest
Posts: n/a

 07-09-2010
On 2010-07-08, jacob navia <(E-Mail Removed)> wrote:
> The second macro supposes that all alignment problems disappear if we
> align to sizeof void *. Has anyone here an example where that is not true?

Tons, double is often larger than void *.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / (E-Mail Removed)
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Ian Collins
Guest
Posts: n/a

 07-09-2010
On 07/ 9/10 01:36 PM, Seebs wrote:
> On 2010-07-08, jacob navia<(E-Mail Removed)> wrote:
>> The second macro supposes that all alignment problems disappear if we
>> align to sizeof void *. Has anyone here an example where that is not true?

>
> Tons, double is often larger than void *.

Double the size...

--
Ian Collins

jacob navia
Guest
Posts: n/a

 07-09-2010
Ian Collins a écrit :
> On 07/ 9/10 01:36 PM, Seebs wrote:
>> On 2010-07-08, jacob navia<(E-Mail Removed)> wrote:
>>> The second macro supposes that all alignment problems disappear if we
>>> align to sizeof void *. Has anyone here an example where that is not
>>> true?

>>
>> Tons, double is often larger than void *.

>
> Double the size...
>

That woiuld be a C++ answer, not a C answer Ian. Suppose you want to
store shorts in your container (size 2). You would end up rounding
to 16 for each short, i.e. an overhead of 800%, multiplying by
8 the storage requirements.

Impossible.

jacob navia
Guest
Posts: n/a

 07-09-2010
Seebs a écrit :
> On 2010-07-08, jacob navia <(E-Mail Removed)> wrote:
>> The second macro supposes that all alignment problems disappear if we
>> align to sizeof void *. Has anyone here an example where that is not true?

>
> Tons, double is often larger than void *.
>
> -s

Yes, but that doesn't matter since

(1) You store doubles. Size is 8, and roundup requirements are 4, say,
and in that case no alignment will be performed at all and everything
will work "out of the box" since 8 is a multiple of 4.

(2) You store the doubles in a structure. In that case the compiler will
have done the alignment for you.

Ian Collins
Guest
Posts: n/a

 07-09-2010
On 07/ 9/10 05:03 PM, jacob navia wrote:
> Ian Collins a écrit :
>> On 07/ 9/10 01:36 PM, Seebs wrote:
>>> On 2010-07-08, jacob navia<(E-Mail Removed)> wrote:
>>>> The second macro supposes that all alignment problems disappear if we
>>>> align to sizeof void *. Has anyone here an example where that is not
>>>> true?
>>>
>>> Tons, double is often larger than void *.

>>
>> Double the size...

>
> That woiuld be a C++ answer, not a C answer Ian.

It was intended as a pun...

--
Ian Collins