E
Eric Sosman
Why said:Eric, thanks for the very detailed answer. But there is still something
that is not clear to me.
Suppose the following:
sizeof(SomeStruct) = 8
sizeof(UserStruct) = 16
malloc() will see a request of 24 byte allocation. How does it work out
whether alignment is at 4 byte, 8 byte or 16 byte boundary?
Since malloc() is part of the implementation, it can use
"insider information" that isn't available outside the boardroom.
Among other things, malloc() knows the alignment requirements of
all types on its own implementation. For example, malloc() might
"just know" that on a particular machine the strictest alignment
required for any type at all is eight bytes; knowing this, malloc()
can simply return eight-byte-aligned memory for every request, and
then it doesn't need to worry about whether the caller will use the
memory for three eight-byte longs or twelve two-byte shorts or
twenty-four characters or a struct of several elements or ...
The C Standard says that a successful malloc() obtains memory
that 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." In
effect, the Standard not only sanctions but requires malloc() to
use the strategy outlined above. There is an angels-on-pinheads
quibble about whether malloc(4), say, needs to satisfy alignment
requirements that only apply to objects of eight bytes or larger;
if long and double and long double are the only types requiring
eight-byte alignment and they are all eight bytes long, clearly
the caller is not going to store one of them (or a struct that
holds one of them) in the memory obtained by malloc(4). If the
program does so it invokes undefined behavior anyhow, so malloc(4)
might return a more loosely-aligned memory block. Whether this is
legal or not has been debated a few times; both sides of the argument
have their adherents.
Based on the assumption above, if we were to assume the stricter
UserStruct comes first, will it avoid the problem?
Probably. It is conceivable, I suppose, that a bizarre machine
might have alignment requirements that are not multiples of each
other: four-byte alignment for int, say, and ten-byte alignment
for long double. On such a machine the only way an int and a
long double could be adjacent would be if one was just before and
one just after a twenty-byte boundary -- and since malloc() would
need to return twenty-byte-aligned memory, it would never be
possible to juxtapose the two objects at the start of a malloc'ed
memory area. (The second would always be mis-aligned, no matter
which one it was.) Personally, I have never run into a machine
with such bizarre alignment requirements and I never expect to,
but the C Standard doesn't rule it out.
A more practical problem is to determine which of the two
types has the stricter alignment. There's a cute little hack
floating about that lets you make a pretty good guess about the
alignment needed for a known type -- Google +alignof +offsetof --
but you need the actual type name, not just the type's size.