Healthy skepticism towards documentation (was: effect of free)

Steve Summit scs at hstbme.mit.edu
Sat Sep 9 16:19:31 AEST 1989


In article <10817 at riks.csl.sony.co.jp> diamond at riks. (Norman Diamond) writes:
>Well, because a freed pointer is still valid in a call to realloc
>(as long as there are no intervening *alloc calls), ...

In article <10990 at smoke.BRL.MIL> gwyn at brl.arpa (Doug Gwyn) writes:
>Nope.  That guarantee that you've read in some MALLOC(3) UNIX manual
>page, was documenting an arguably useful feature of a particular
>implementation.

Important though it is (and some documentation is certainly
better than no documentation at all) it's often a good idea to
take documentation with a grain of salt.  The first time I read

	The argument to free is a pointer to a block previously
	allocated by malloc; this space is made available for
	further allocation, but its contents are left undisturbed.

on the malloc(3) page, I said to myself "what in the world are
they guaranteeing something like that for?"  It's a patently
dangerous assertion, bound to disappear in the future.  I've
never depended on it.  (I've written versions of free which
deliberately scribble on the freed region to catch programs which
accidentally depend on it.)

There's another useless guarantee on many old malloc(3) pages:

	realloc also works if ptr points to a block freed since
	the last call of malloc, realloc or calloc; sequences of
	free, malloc and realloc can exploit the search strategy
	of malloc to do storage compaction.

Someone noticed this quirk in an early malloc implementation;
the practice of implementing storage compaction in this way
became so widespread that later implementations have had to bend
way over backwards to "support" the contorted usage.

"But," you say, "storage compaction is important, especially on
those old systems with limited memory.  How else were we supposed
to do it?"  Easy.  Write a routine called storagecompact(),
containing whatever contorted code it takes to compact storage
(if it's some fortuitous combination of calls to free, malloc,
and realloc, so be it) and document _that_ as the way to do
storage compaction, if you need to.


Unfortunately, sometimes our friend the FM is actually F'ed.
Other examples:

	Countless unsuspecting programmers have seen

		execl(name, arg0, arg1, ..., argn, 0)

	on the EXEC(2) man page and have decided that, arguments
	on comp.lang.c to the contrary notwithstanding, they can
	pass uncast null pointers with impunity and it should
	work.  (The last argument should of course be (char *)0 .)

	The man page for dup and dup2 used to warn that dup2 was
	not portable to non-Unix systems, so people tend to
	simulate dup2 with even less portable usages of dup.

	For some reason Berkeley likes to deprecate its backwards-
	compatibility stubs.  CREAT(2) says, in big bold letters,

		This interface is made obsolete by open(2).

	This sort of thing only encourages people to write code
	which won't compile anywhere else.  (Of course, a three-
	argument open is common now, and Posix condones it, but
	Posix also supports creat, which is likely to hang around
	for quite a while because, obsolete or not, there's a lot
	of working code out there which uses it and which
	shouldn't need to be rewritten.)  Similar cautions appear
	on the man pages for alarm, signal, and time.

Of course, the next question is, if you can't trust the
documentation, what can you trust?  (It used to be the source
code, but fewer people have access to it in these days of
restrictive licensing.)  There's no answer, of course; all you
can do is keep your head on straight and don't be afraid to
question something that doesn't look right.  The BUGS line on
learn(1) is appropriate:

	Occasionally lessons are incorrect.  Such lessons may be
	skipped with the `skip' command, but it takes some
	sophistication to recognize the situation.

                                                Steve Summit



More information about the Comp.lang.c mailing list