Xref: utzoo comp.std.c:1816 comp.lang.c:22850 Path: utzoo!attcan!uunet!munnari.oz.au!csc!arp!anucsd!bdm From: bdm@anucsd.oz (Brendan McKay) Newsgroups: comp.std.c,comp.lang.c Subject: Common malloc/free practice violates ANSI standard ? Message-ID: <1989Oct14.043811.669@anucsd.oz> Date: 14 Oct 89 04:38:11 GMT Organization: Comp Sci, Australian National Uni, Canberra Lines: 53 [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@anucsd.oz or bdm@anucsd.oz.au