malloc and alignment question

D

David Mathog

Sorry if this is in the FAQ, been through it a couple of times and
could not find a clear answer.

The question concerns this code snippet:

long *lvar;
char *cvar;
lvar = malloc(132);
cvar=malloc(132);

Presumably the C compiler will always align the memory allocated on
the 3rd line so that the
132/sizeof(long) long's that could be stored there are properly
aligned for the target machine. The
question is, given the existence of the longer data type, must the
memory returned in the last line _also_ be properly aligned for longs?

For instance it was claimed here:
http://bytes.com/topic/c/answers/220448-how-get-aliagned-memory-using-malloc

that

The C standard specifies that malloc() and family will allocate
memory
so that the address can be used for any data type. This means that
malloc() and family must be familiar with and able to accomodate the
restrictions the underlying platform place on the arrangement of
data
items in memory.

malloc is a low level routine and its only parameter is the size of
the memory to allocate. It would seem that the only way to reconcile
the quote above with the single parameter nature of malloc would be to
have malloc always return an address which is the least common
multiple of all defined data types for the target. Or are compilers
allowed to replace malloc with malloc_4bytes, malloc_2bytes
etc., to achieve an alignment appropriate for only the target pointer,
but possibly not for larger types?

Thanks,

David Mathog
 
K

Keith Thompson

David Mathog said:
Sorry if this is in the FAQ, been through it a couple of times and
could not find a clear answer.

The question concerns this code snippet:

long *lvar;
char *cvar;
lvar = malloc(132);
cvar=malloc(132);

Presumably the C compiler will always align the memory allocated on
the 3rd line so that the
132/sizeof(long) long's that could be stored there are properly
aligned for the target machine. The
question is, given the existence of the longer data type, must the
memory returned in the last line _also_ be properly aligned for longs?

Yes.

C99 7.20.3p1:

The pointer returned if the allocation succeeds is suitably
aligned so that it may be assigned to a pointer to any type
of object and then used to access such an object or an array
of such objects in the space allocated (until the space is
explicitly deallocated).

There's a somewhat interesting corner case: must malloc(1) return a
pointer suitably aligned for types bigger than one byte? But that
doesn't affect your case.

A minor point: If, for example, sizeof(long)==8, lvar points to
a region of memory (assuming malloc succeeded) that can't hold a
whole number of longs. In real life, of course, you'd probably use
something like
lvar = malloc(N * sizeof *lvar);
This isn't particuarly relevant to your question.
 
T

Tim Prince

The C standard specifies that malloc() and family will allocate
memory
so that the address can be used for any data type. This means that
malloc() and family must be familiar with and able to accomodate the
restrictions the underlying platform place on the arrangement of
data
items in memory.

malloc is a low level routine and its only parameter is the size of
the memory to allocate. It would seem that the only way to reconcile
the quote above with the single parameter nature of malloc would be to
have malloc always return an address which is the least common
multiple of all defined data types for the target. Or are compilers
allowed to replace malloc with malloc_4bytes, malloc_2bytes
etc., to achieve an alignment appropriate for only the target pointer,
but possibly not for larger types?

Surely, you must be aware of the unfriendly interpretations taken by the
ABIs of certain common OS. 32-bit windows assures only 4-byte
alignment, which is considered to meet the letter, if not the spirit, of
the above wording, as hardware can deal with misalignment, other than in
certain vectorized contexts, with varying degrees of performance
penalty. As sizeof(long) is 4, and long long is implemented by pairs of
32-bit data, no big problem arises until double or parallel data types
are encountered. The advent of widespread 256-bit data hardware support
expected next year may not be relevant in a rehash of issues of a decade
or more standing.
 
T

Tim Rentsch

David Mathog said:
Sorry if this is in the FAQ, been through it a couple of times and
could not find a clear answer.

The question concerns this code snippet:

long *lvar;
char *cvar;
lvar = malloc(132);
cvar=malloc(132);

Presumably the C compiler will always align the memory allocated on
the 3rd line so that the
132/sizeof(long) long's that could be stored there are properly
aligned for the target machine. The
question is, given the existence of the longer data type, must the
memory returned in the last line _also_ be properly aligned for longs?

For instance it was claimed here:
http://bytes.com/topic/c/answers/220448-how-get-aliagned-memory-using-malloc

that

The C standard specifies that malloc() and family will allocate memory
so that the address can be used for any data type. This means that
malloc() and family must be familiar with and able to accomodate the
restrictions the underlying platform place on the arrangement of data
items in memory.

malloc is a low level routine and its only parameter is the size of
the memory to allocate. It would seem that the only way to reconcile
the quote above with the single parameter nature of malloc would be to
have malloc always return an address which is the least common
multiple of all defined data types for the target. Or are compilers
allowed to replace malloc with malloc_4bytes, malloc_2bytes
etc., to achieve an alignment appropriate for only the target pointer,
but possibly not for larger types?

Quoting from 7.20.3 p1::

"The pointer returned if the allocation succeeds is suitably
aligned so that it may be assigned to a pointer to any type
of object and ...."

I don't see any wiggle room. The memory allocated must have
an address that satisfies the alignment requirements of /all/
data types, no matter how large.
 
T

Tim Rentsch

Keith Thompson said:
David Mathog said:
Sorry if this is in the FAQ, been through it a couple of times and
could not find a clear answer.

The question concerns this code snippet:

long *lvar;
char *cvar;
lvar = malloc(132);
cvar=malloc(132);

Presumably the C compiler will always align the memory allocated on
the 3rd line so that the
132/sizeof(long) long's that could be stored there are properly
aligned for the target machine. The
question is, given the existence of the longer data type, must the
memory returned in the last line _also_ be properly aligned for longs?

Yes.

C99 7.20.3p1:

The pointer returned if the allocation succeeds is suitably
aligned so that it may be assigned to a pointer to any type
of object and then used to access such an object or an array
of such objects in the space allocated (until the space is
explicitly deallocated).

There's a somewhat interesting corner case: must malloc(1) return a
pointer suitably aligned for types bigger than one byte? [snip]

The result of any malloc() call, even malloc(1), must be suitably
aligned so that it may be assigned to a pointer of any type.
Given that, how could the answer to the last question be anything
but "Yes."?
 
D

David Mathog


Ah good. I was trying to determine if this snippet should be portable
(the size
always was supposed to be a multiple of 2, I just typed in the wrong
values in the
first example):

#define ASIZE 128
unsigned char *cval;
unsigned char *bval;
int status;
cval=malloc(ASIZE);
bval=malloc(ASIZE);
/* code goes here that checks cval,bval fill the arrays with data */
status=xorfunction((unsigned long *)cval, (unsigned long *)bval);

where

int xorfunction(unsigned char *cl, unsigned char *bl){
unsigned long test=0;
int i;
for(i=0; i<ASIZE/sizeof(unsigned long); i++, cl++, bl++){
*cl = *cl ^ *bl;
test |= *cl;
}
if(test)return(1);
return(0);
}

The idea being to simultaneously XOR the bval and cval arrays and also
to detect if
the result consists of all null bytes. Those operations will work in
parallel on multiple char
using a larger integer, but I wanted to be sure that the simple
malloc() was enough to guarantee that
the larger integers would align naturally on the data.

Thanks,

David Mathog
 
B

Ben Bacarisse

David Mathog said:
#define ASIZE 128
unsigned char *cval;
unsigned char *bval;
int status;
cval=malloc(ASIZE);
bval=malloc(ASIZE);
/* code goes here that checks cval,bval fill the arrays with data */
status=xorfunction((unsigned long *)cval, (unsigned long *)bval);

where

int xorfunction(unsigned char *cl, unsigned char *bl){

I think you mean unsigned long *cl (and the same for bl) here.

By the way, if you make cval and bval void *, you can do away with the
casts (provided there is a prototype in scope, but that is standard
practise these days).
unsigned long test=0;
int i;
for(i=0; i<ASIZE/sizeof(unsigned long); i++, cl++, bl++){
*cl = *cl ^ *bl;
test |= *cl;
}
if(test)return(1);
return(0);
}

<snip>
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
C99 7.20.3p1:

The pointer returned if the allocation succeeds is suitably
aligned so that it may be assigned to a pointer to any type
of object and then used to access such an object or an array
of such objects in the space allocated (until the space is
explicitly deallocated).

There's a somewhat interesting corner case: must malloc(1) return a
pointer suitably aligned for types bigger than one byte? [snip]

The result of any malloc() call, even malloc(1), must be suitably
aligned so that it may be assigned to a pointer of any type.
Given that, how could the answer to the last question be anything
but "Yes."?

I agree that, since the standard clearly states it must be suitably
aligned, it must be suitably aligned. But an implementation could fail
to meet that requirement without affecting the visible behavior of any
<handwave>portable</handwave> program.

If there is never any effect on a program's visible behavior, the
requirement has been met, right? Just the usual "as if" rule.
Given:

void *p = malloc(1);

how can you tell whether p is suitably aligned for long double?
[snip example using comparison]

The question is what test can be done to show that p /isn't/
suitably aligned. Just assign p to a variable of appropriate
pointer type:

long double *pld = p;
printf( "did malloc() allocate? %s.\n", pld ? "Yes" : "No" );

These lines of code must always work (assuming appropriate
headers and other context) and must always output "Yes" or
"No". Any other result means the implementation isn't
conforming. Considering any given implementation, if there
isn't any correct program that shows a difference between
the program's actual behavior and what the Standard requires
(modulo the specific implementation-defined behavior it
supplies), then that implementation is conforming -- whether
we can prove it or not -- and that includes the condition of
malloc(1) results being suitably aligned, by definition.
 

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

Similar Threads

malloc and alignment 13
malloc and maximum size 56
Alignment (K&R question) 13
malloc() and alignment 10
Data alignment questin, structures 46
Malloc question 9
Alignment problems 20
malloc() and alignment 12

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,059
Latest member
cryptoseoagencies

Latest Threads

Top