Common malloc/free practice violates ANSI standard ?

Brendan McKay bdm at anucsd.oz
Sat Oct 14 14:38:11 AEST 1989


[I thought I posted this a month ago, but since I didn't get a single bite,
I suspect it didn't get out.  Apologies if you just thought it was too boring.]

Consider the following piece of code, where OBJ is an arbitrary type name.

        OBJ *objptr;

        objptr = (OBJ*)malloc( sizeof(OBJ) );
        ...
        free( (void*)objptr );

This use of malloc() and free() is of course very commonplace.  [In fact,
the Rationale which accompanies the draft standard has an example which does
it this way.]  However, I wish to argue that the draft ANSI standard does not
permit it.  (Actually, I'm looking at the draft of May 15, 1987, so apologies
if the relevant parts have changed since then.)

malloc() returns a value of type void*, "suitably aligned so that it may be
assigned to a pointer to any type of object and then used to access such an
object..." (Section 4.10.3).  Thus, it is clear that we may use the value
assigned to objptr without worry.  The trouble comes with the call to free(),
who's argument must "match a pointer earlier returned by the [malloc] function".

Consider the following hypothetical implementation:
* pointers are implemented as memory addresses in the common way
* objects of type OBJ require even addresses.
* assigning a void* to an OBJ* involves rounding up to an even address
* malloc allocates sufficient space so that it will cover an object of
  type OBJ even when the void* value returned is rounded up to even.
  (Thus, sometimes it actually allocates one more cell than it is asked for.)
* assigning an OBJ* to a void* involves no change of address

This implementation is unusual, but seems to obey the rules.  There was no
requirement that malloc() return an even address, only that the value
returned could be used after casting to OBJ*.  However, when objptr is cast
back to void* for passing to free(), the value obtained is possibly different
from the one returned by malloc(), thus breaking the rules for free().

No doubt this problem was unintentional.  It could easily be fixed by a
sentence reading something like
"The pointer returned if the allocation succeeds is such that, if it is cast
to a pointer to any type of object and then that pointer is cast to type void*,
the original value is recovered."

Note that I'm not claiming the Standard is broken, only that the writers of
the standard have accidentally ruled out a common coding practice.


Brendan D. McKay
Computer Science Department
Australian National University

bdm at anucsd.oz  or  bdm at anucsd.oz.au



More information about the Comp.std.c mailing list