Seebs said:
[...]
It doesn't matter how easy or hard it is for the implementor to comply.
They are *REQUIRED* to correctly do nothing without crashing if a null
pointer is passed to free(). As it happens, this is very easy.
You may get away with it, but passing a NULL pointer to free is a mark of
careless code, it should never happen.
The ability to free(NULL) is convenient, not usually in that
exact guise but in a realloc(NULL,...) setting:
char *buff = NULL;
size_t buffsiz = 0;
...
while (something) {
...
if (len > buffsiz) {
char *temp = realloc(buff, buffsiz = len * 2);
if (temp == NULL) ...
buff = temp;
}
...
}
Without the ability to realloc(NULL,...), the buffer-growing code
would need to make a special case of the initial allocation, or
else the initial allocation would need to occur before the loop
(and the error-handling would need to be duplicated). Given that
realloc(NULL,...) is so handy, free(NULL) is pretty much a given --
"for free," as it were.
Making free check if it was passed a bad pointer is completely against
the spirit of C.
The Committee that wrote the C Standard twenty-plus years ago
paid a good deal of attention to the "spirit of C," and went so far
as to write down just what they thought the S.O.C. meant (see the
Rationale). Since they wrote the "free(NULL) is a no-op" requirement,
they plainly disagreed with your notions of the S.O.C.
There are no checks for division by 0, no checks for
array bounds - the programmer is expected and trusted to know what he is
doing.
The C Standard does not forbid either of these types of checks.
Indeed, division by zero *is* checked on *every* C implementation I've
used in the last three and a half decades.
As for "trust the programmer," yes: That's part of the S.O.C.
and the Rationale says so in exactly those words. (I consider it
unfortunate that the C1x Committee appears to be backing away from
this ideal -- but given the existence of programmers who think it a
good idea not to check for NULLs from malloc(), perhaps "trust the
programmer" is indeed no longer viable.)
It should be the same with passing a valid pointer to free and no
good programmer should pass in a NULL pointer whether or not he will get
away with it.
It's not a matter of "getting away with" anything at all. NULL
*is* a valid argument to free() and a valid first argument to realloc(),
and there's no reason for a programmer to avoid passing valid arguments.
What would you think of
int y = (x >= 0 ? x : abs(x));
.... to avoid a no-op of another kind?
Forcing free to test for NULL is pointless and inefficient
if the programmer is competent.
"Pointless" is a matter of opinion, and we can disagree about
matters of opinion. But "inefficient" has a more quantitative basis;
I'd be interested to see the measurements you've made of the penalty
free() incurs by testing whether its argument is NULL. (Suggestion:
Get hold of an open-source memory management library, maybe glibc,
and build versions with and without the NULL test in free(). Run a
suite of actual programs with both library versions, and measure the
speed difference. Discuss.)
Finally, there's your "if the programmer is competent" line.
I put it to you that a programmer who fails to check the value of
malloc(), realloc(), or calloc() against NULL is not competent,
not competent enough to write C at any rate.