Allocating memory aligned on a given boundary

K

K. Jennings

I would like to get the result of malloc() such that it is
aligned on a given boundary - 8, in this case. Assuming that sizeof(u64)
is 8, will

u64 *p = malloc(N) ;

do the trick in general?

Here N is a positive integer, and I am assuming that malloc()
succeeds in allocating the chunk of memory specified.

This seems to work, but I do not know whether it is just my
compiler, or a general rule in C.
 
R

Richard Heathfield

K. Jennings said:
I would like to get the result of malloc() such that it is
aligned on a given boundary - 8, in this case. Assuming that
sizeof(u64) is 8, will

u64 *p = malloc(N) ;

do the trick in general?

The C Standard guarantees that malloc's result (if not NULL) is always
correctly aligned for any object type.
 
F

Flash Gordon

Richard Heathfield wrote, On 24/04/07 17:41:
K. Jennings said:


The C Standard guarantees that malloc's result (if not NULL) is always
correctly aligned for any object type.

However it makes no guarantees about what the alignment might be nor any
way to find out. So if you really want a specific alignment, for example
so that you can use some highly system specific tricks, you will need to
use some highly system specific method. Any such methods and tricks
would be off topic here so you would have to ask in a group dealing with
the specific platform(s) of interest.
 
W

Walter Roberson

K. Jennings said:
The C Standard guarantees that malloc's result (if not NULL) is always
correctly aligned for any object type.

Expanding slightly:

This means that if the particular implementation is able and
willing to handle u64's (and everything else) on (say) 4 byte boundaries,
then malloc(sizeof u64) is not guaranteed to be aligned on a multiple
of sizeof u64. The guarantee is only that it will be allocated on
an accessible boundary. The difference between accessible boundaries
and specific alignment boundaries (e.g., 8) can sometimes be of
concern, such as if you are trying to take into account cache effects.
 
A

Army1987

K. Jennings said:
I would like to get the result of malloc() such that it is
aligned on a given boundary - 8, in this case. Assuming that sizeof(u64)
is 8, will

u64 *p = malloc(N) ;

do the trick in general?

Here N is a positive integer, and I am assuming that malloc()
succeeds in allocating the chunk of memory specified.

Is the real question "What happens if N isn't a multiple of 8?"?
 
E

Eric Sosman

K. Jennings wrote On 04/24/07 15:43,:
No. The actual value of N is irrelevant, as far as that is
concerned.

Are you still seeking answers, and if so, to what?
To summarize what's appeared thus far: A successful malloc()
allocates memory that is suitably aligned for all C data
types (but not necessarily for non-C "types" like "pages"),
and there is no portable way to discover what the "suitable
for all types" alignment requirement is, nor even to discover
the alignment of any particular allocation. Does this answer
your question, or is there something else you hope to learn?
 
K

K. Jennings

K. Jennings wrote On 04/24/07 15:43,:

Are you still seeking answers, and if so, to what?
To summarize what's appeared thus far: A successful malloc() allocates
memory that is suitably aligned for all C data types (but not
necessarily for non-C "types" like "pages"), and there is no portable
way to discover what the "suitable for all types" alignment requirement
is, nor even to discover the alignment of any particular allocation.
Does this answer your question, or is there something else you hope to
learn?

I think I have the info that I wanted. If I understand it
correctly, it makes no difference whether you do

u64 *p = malloc(N) ;

or

char *p = malloc(N) ;

the address returned, when non-NULL, will be aligned on a boundary equal
to the largest basic data size supported. Thus, for 32-bit architectures
it might be either 4 or 8 bytes, whereas for 64-bit ones it would be 8.
Or am I missing something?
 
I

Ian Collins

K. Jennings said:
I think I have the info that I wanted. If I understand it
correctly, it makes no difference whether you do

u64 *p = malloc(N) ;

or

char *p = malloc(N) ;

the address returned, when non-NULL, will be aligned on a boundary equal
to the largest basic data size supported. Thus, for 32-bit architectures
it might be either 4 or 8 bytes, whereas for 64-bit ones it would be 8.
Or am I missing something?

Or it might be something else if there is a bigger type (long double for
example). On my boxes, the alignment is 16 on 32 and 64 bit
(sizeof(long double) == 12 ).
 
R

Richard Bos

K. Jennings said:
I think I have the info that I wanted. If I understand it
correctly, it makes no difference whether you do

u64 *p = malloc(N) ;

or

char *p = malloc(N) ;

the address returned, when non-NULL, will be aligned on a boundary equal
to the largest basic data size supported.

No, it will be aligned at least on the strictest required alignment
boundary. Often, that will be the same as the largest basic type size,
but that's not necessarily true. For example...
Thus, for 32-bit architectures it might be either 4 or 8 bytes, whereas
for 64-bit ones it would be 8.

....that 8-byte type might only need an alignment of 4 bytes, i.e., it
could be legally aligned on boundaries that are only half its own size
apart.
On some systems, there might not be any alignment requirements at all.
All objects, regardless of size, could be located anywhere in memory. On
that system, malloc() could return pointers at any position.
OTOH, on some systems, malloc() could return pointers that are more
widely aligned than the most restrictive basic type needs. Apart from a
requirement of the underlying hardware, I cannot think of any good
reason why it should, but you can't assume that it doesn't.

And then there are the _really_ wild systems, where long ints are 4
bytes but doubles are 5 bytes, and void *s 7... in which case, malloc()
would need to return pointers aligned to 4*5*7==140 byte boundaries. I
don't know of any example of this in practice, but it could exist, there
might be good reasons for it to exist, and the Standard doesn't forbid
it. So really, my first sentence in this post should be "No, it will be
aligned to the least common multiple of all basic object type sizes".

Richard
 
E

Eric Sosman

K. Jennings said:
[...]

I think I have the info that I wanted. If I understand it
correctly, it makes no difference whether you do

u64 *p = malloc(N) ;

or

char *p = malloc(N) ;

the address returned, when non-NULL, will be aligned on a boundary equal
to the largest basic data size supported. Thus, for 32-bit architectures
it might be either 4 or 8 bytes, whereas for 64-bit ones it would be 8.
Or am I missing something?

You're right about the first part: The memory is suitably
aligned for any C data type whatsoever. But you stray from the
Tao beginning at "Thus." The alignment requirement for type T
must be a divisor of sizeof(T) (otherwise arrays wouldn't work),
but need not be equal to sizeof(T).

For your 64-bit data type (assuming an 8-bit char), the
alignment requirement might be any of 1,2,4, or 8.
 
E

Eric Sosman

K. Jennings said:
[...]

I think I have the info that I wanted. If I understand it
correctly, it makes no difference whether you do

u64 *p = malloc(N) ;

or

char *p = malloc(N) ;

the address returned, when non-NULL, will be aligned on a boundary equal
to the largest basic data size supported. Thus, for 32-bit architectures
it might be either 4 or 8 bytes, whereas for 64-bit ones it would be 8.
Or am I missing something?

Earlier I wrote that you were "right about the first part,"
but I'd read too hastily. The non-NULL malloc() result will
meet the *alignment requirement* of all C types, which might
be smaller than the sizeof's one or more basic types. Alignment
divides sizeof, but need not be equal to it.

(Memo to self: Allow coffee to take hold before posting.)
 
K

Kenneth Brody

K. Jennings said:
I think I have the info that I wanted. If I understand it
correctly, it makes no difference whether you do

u64 *p = malloc(N) ;

or

char *p = malloc(N) ;

the address returned, when non-NULL, will be aligned on a boundary equal
to the largest basic data size supported. Thus, for 32-bit architectures
it might be either 4 or 8 bytes, whereas for 64-bit ones it would be 8.
Or am I missing something?

All that's guaranteed is that it's _properly_aligned_ for any type.
This does not necessarily mean that it is, using your example,
aligned to sizeof(longest_type). You may have a 64-bit "long long"
type, yet still get 4-byte (ie: 32-bit) alignment. The alignment
may also be larger than the minimum needed by the hardware. For
example, my system returns 8-byte alignment, even though the
hardware itself would be happy with 2-byte alignment (and happier
with 4-byte alignment). This is simply because the implementation
decided to do so for its own convenience, as it allows it to use
the low-order 3 bits of pointers within the heap for its own use.
Also, way back in MS-DOS days, I used an implementation which
returned 16-byte alignment, even though 1-byte alignment would
have sufficed. This allowed malloc's "far pointers" to always
have a zero offset, as I recall. (Another great reason for
making sure you include the correct headers, as without the
proper return type declared, the assumption of "int" would have
meant you would always see a zero return.)

As others have stated, there is no portable way to know what the
alignment is. Nor is there likely any need to know, as all you
really should care about is that the alignment is valid. (Unless
you are writing your own malloc, and you need to know that you
are implementing it correctly.)

Why do you think you need to determine malloc's alignment?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Kenneth Brody

Richard Bos wrote:
[...]
OTOH, on some systems, malloc() could return pointers that are more
widely aligned than the most restrictive basic type needs. Apart from a
requirement of the underlying hardware, I cannot think of any good
reason why it should, but you can't assume that it doesn't.
[...]

I have seen such implementations (ie: 8-byte alignment from malloc,
despite only needing 2- or 4-byte alignment). In those cases, the
heap was managed with a singly-linked list, and within the header
of each chunk of the heap was a "next" pointer. (Or maybe it was
"block length"?) In any case, the low-order 3 bits of these values
were used for some internal status flags, as the actual value was
guaranteed to have the low-order 3 bits as zero.

Also, way back in MS-DOS days, the compiler I used had 16-byte
alignment for malloc. This meant it could guarantee that the
segment:eek:ffset value returned (in "large mode") would always have
a zero offset.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Keith Thompson

Eric Sosman said:
K. Jennings said:
[...]
I think I have the info that I wanted. If I understand it
correctly, it makes no difference whether you do
u64 *p = malloc(N) ;
or
char *p = malloc(N) ;
the address returned, when non-NULL, will be aligned on a boundary
equal to the largest basic data size supported. Thus, for 32-bit
architectures it might be either 4 or 8 bytes, whereas for 64-bit
ones it would be 8. Or am I missing something?

You're right about the first part: The memory is suitably
aligned for any C data type whatsoever. But you stray from the
Tao beginning at "Thus." The alignment requirement for type T
must be a divisor of sizeof(T) (otherwise arrays wouldn't work),
but need not be equal to sizeof(T).

For your 64-bit data type (assuming an 8-bit char), the
alignment requirement might be any of 1,2,4, or 8.

But he said "32-bit architectures", not "32-bit types". A system with
a 32-bit architecture could require 1, 2, 4, or 8-byte alignment for a
64-bit type (again assuming CHAR_BIT==8).

Of course the phrases "32-bit architecture" and "64-bit architecture"
are very vaguely defined, and neither necessarily implies any specific
alignment requirements.
 
D

Doug

K. Jennings wrote On 04/24/07 15:43,:







Are you still seeking answers, and if so, to what?
To summarize what's appeared thus far: A successful malloc()
allocates memory that is suitably aligned for all C data
types (but not necessarily for non-C "types" like "pages"),
and there is no portable way to discover what the "suitable
for all types" alignment requirement is, nor even to discover
the alignment of any particular allocation. Does this answer
your question, or is there something else you hope to learn?

No, I think you've patronised him enough.
 
C

CBFalconer

Eric said:
.... snip ...

You're right about the first part: The memory is suitably
aligned for any C data type whatsoever. But you stray from the
Tao beginning at "Thus." The alignment requirement for type T
must be a divisor of sizeof(T) (otherwise arrays wouldn't work),
but need not be equal to sizeof(T).

That depends on the hardware. Some just don't care.
 
D

Dave Vandervies

That depends on the hardware. Some just don't care.

If the hardware doesn't care, then the alignment requirement is 1 byte,
which divides sizeof(T) for any T.


dave
 
E

Eric Sosman

Doug said:
No, I think you've patronised him enough.

It was an honest question: The answers seemed to have been
given and validated, yet the discussion carried on (and with the
O.P.'s participation). Why? Was there, perhaps, an unstated
question lurking somewhere in the background, or a confusion
about some aspect of the answers? That's why I asked, much as
the butlers in those drawing-room comedies ask "Will there be
anything else, m'lud?"

... and as it turned out, the O.P. *was* still confused a
bit about the distinction between sizeof and alignment, so my
prompting was not entirely wasted. (What was wasted was my
next response, a miracle of misreading and sloppy composition.
Ah, well, that's Usenet: Advice worth every penny paid.)
 
E

Eric Sosman

CBFalconer said:
Not necessarily. The compiler may be adjusting for speed reasons.

.... in which case it's imposing an alignment requirement that
isn't forced upon it by the hardware. There's nothing wrong
with that; nowhere does the Standard say that alignment must
be dictated by the hardware alone.

Whatever the alignment requirement and whatever the reason
for imposing it, it must be an exact divisor of sizeof(T).
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,164
Latest member
quinoxflush
Top