Post by Chris DollinPost by CBFalconerPost by Chris DollinI am not arguing that the choice "malloc(0) always returns the
same pointer" would be /sensible/ if it were legal, just that
it could be made to work consistently.
No it couldn't. Think about pointer comparisons. Then think about
what other anomalies could exist. But one is enough to show it is
a bad idea.
I'm thinking, but I can't see an anomaly. I'm probably just being
dim.
Since malloc() is a reserved function name, let me illustrate with
a different function-name. This also lets me use malloc() for the
"hard parts".
#include <stdlib.h>
static char magic;
void *nalloc(size_t size) {
if (size == 0)
return &magic; /* or: return NULL */
return malloc(size);
}
void nfree(void *p) {
if (p != &magic)
free(p);
}
void nrealloc(void *p, size_t size) {
if (p == &magic)
p = NULL;
if (size == 0) {
free(p);
return &magic; /* or: return NULL */
}
return realloc(p, size);
}
Given the obvious preconditions, the behavior of this code is
well-defined (which may suffice to label it "sensible"), but would
it suffice to replicate the Standard's requirements for malloc()?
I believe the answer is "no":
/* insert appropriate #include lines, etc., as needed */
#define Xalloc nalloc /* or malloc */
#define NAME "nalloc" /* or "malloc" */
#define Xfree nfree /* or free */
void check_it(void) {
void *p1 = Xalloc(0);
void *p2 = Xalloc(0);
if (p1 == NULL && p2 == NULL)
puts("OK: " NAME "(0) returned NULL each time");
else if (p1 == p2)
puts("FAIL: p1 == p2, but p1 and p2 are not NULL");
else {
puts("OK: alloc(0), called twice, returned two different")
puts("non-NULLs, or one non-NULL and one NULL");
}
Xfree(p1);
Xfree(p2);
}
If we use this check_it() routine on nalloc(), it will print the
"FAIL" line, because p1 and p2 are equal, yet at least one of the
two pointers is not NULL (in fact both point to the "magic" byte).
What if we replace the "return &magic" lines with "return NULL"?
Then I believe nalloc() satisfies the requirements for malloc().
Note that if one modifies check_it() -- or rather, the variant of
check_it() that uses malloc() -- to call free() on either p1 or p2
before testing their values, the check_it() function itself becomes
invalid: an attempt to use the value of a non-NULL pointer variable
that was once valid, but has since been passed to free(), causes
undefined behavior (<http://web.torek.net/torek/c/numbers2.html>).
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.