Actually, the last of those is equivalent to a call to free()
. Read the specification of realloc()
very carefully, and you will find it can allocate data anew, or change the size of an allocation (which, if the new size is larger than the old, might move the data around), and it can release memory too. In fact, you don't need the other functions; they can all be written in terms of realloc()
. Not that anyone in their right mind would do so...but it could be done.
See Steve Maguire's "Writing Solid Code" for a complete dissection of the perils of the malloc()
family of functions. See the ACCU web site for a complete dissection of the perils of reading "Writing Solid Code". I'm not convinced it is as bad as the reviews make it out to be - though its complete lack of a treatment of const
does date it (back to the early 90s, when C89 was still new and not widely implemented in full).
D McKee's notes about MacOS X 10.5 (BSD) are interesting...
The C99 standard says:
7.20.3.3 The malloc function
Synopsis
#include <stdlib.h>
void *malloc(size_t size);
Description
The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
Returns
The malloc function returns either a null pointer or a pointer to the allocated space.
7.20.3.4 The realloc function
Synopsis
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
Description
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. The contents of the new
object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by the
calloc, malloc, or realloc function, or if the space has been deallocated by a call
to the free or realloc function, the behavior is undefined. If memory for the new
object cannot be allocated, the old object is not deallocated and its value is unchanged.
Returns
The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.
The Solaris 10 (SPARC) man page for realloc says:
The realloc() function changes the size of the block pointer to by ptr to size bytes and returns a pointer to the (possibly moved) block. The contents will be unchanged up to the
lesser of the new and old sizes. If the new size of the
block requires movement of the block, the space for the previous instantiation of the block is freed. If the new size
is larger, the contents of the newly allocated portion of
the block are unspecified. If ptr is NULL, realloc() behaves
like malloc() for the specified size. If size is 0 and ptr
is not a null pointer, the space pointed to is freed.
That's a pretty explicit 'it works like free()' statement.
However, that MacOS X 10.5 or BSD says anything different reaffirms the "No-one in their right mind" part of my first paragraph.
There is, of course, the C99 Rationale...It says:
7.20.3 Memory management functions
The treatment of null pointers and zero-length allocation requests in the definition of these
functions was in part guided by a desire to support this paradigm:
OBJ * p; // pointer to a variable list of OBJs
/* initial allocation */
p = (OBJ *) calloc(0, sizeof(OBJ));
/* ... */
/* reallocations until size settles */
while(1) {
p = (OBJ *) realloc((void *)p, c * sizeof(OBJ));
/* change value of c or break out of loop */
}
This coding style, not necessarily endorsed by the Committee, is reported to be in widespread
use.
Some implementations have returned non-null values for allocation requests of zero bytes.
Although this strategy has the theoretical advantage of distinguishing between “nothing” and “zero” (an unallocated pointer vs. a pointer to zero-length space), it has the more compelling
theoretical disadvantage of requiring the concept of a zero-length object. Since such objects
cannot be declared, the only way they could come into existence would be through such
allocation requests.
The C89 Committee decided not to accept the idea of zero-length objects. The allocation
functions may therefore return a null pointer for an allocation request of zero bytes. Note that this treatment does not preclude the paradigm outlined above.
QUIET CHANGE IN C89
A program which relies on size-zero allocation requests returning a non-null pointer
will behave differently.
[...]
7.20.3.4 The realloc function
A null first argument is permissible. If the first argument is not null, and the second argument is 0, then the call frees the memory pointed to by the first argument, and a null argument may be
returned; C99 is consistent with the policy of not allowing zero-sized objects.
A new feature of C99: the realloc function was changed to make it clear that the pointed-to
object is deallocated, a new object is allocated, and the content of the new object is the same as
that of the old object up to the lesser of the two sizes. C89 attempted to specify that the new object was the same object as the old object but might have a different address. This conflicts
with other parts of the Standard that assume that the address of an object is constant during its
lifetime. Also, implementations that support an actual allocation when the size is zero do not
necessarily return a null pointer for this case. C89 appeared to require a null return value, and
the Committee felt that this was too restrictive.