The man page says that realloc(ptr, 0) is equivalent to free, even
though it isn't. The text on the man page says

---
realloc()  changes the size of the memory block pointed to by ptr to
size bytes.  The contents will be unchanged to the minimum of the old
and new sizes;  newly  allocated memory  will  be  uninitialized.   If
ptr  is  NULL,  the call is equivalent to malloc(size); if size is equal
to zero, the call is equivalent to free(ptr).  Unless ptr is NULL, it
must have been returned by an earlier call to malloc(), calloc() or
realloc().  If the area pointed to was moved, a free(ptr) is done.
[...]
realloc()  returns a pointer to the newly allocated memory, which is
suitably aligned for any kind of variable and may be different from ptr,
or NULL if the request fails.  If  size  was equal to 0, either NULL or
a pointer suitable to be passed to free() is returned.  If realloc()
fails the original block is left untouched; it is not freed or moved.
---

The C99 standard says:

---
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.
---


glibc implements the behavior specified by the standard, not that
specified on the man page. realloc(NULL, 0) is equivalent to malloc(24),
actually allocating the minimum block (which is 24 bytes at least on my
architecture) instead of doing nothing like free(NULL) does.

One test case to demonstrate this:

#include <stdlib.h>

int main(void) {
    void* ptr = malloc(100);
    // Man page says this is equivalent to free(ptr)
    ptr = realloc(ptr, 0);
    // ... but according to Valgrind, this program leaks memory,
    // unless you add
    free(ptr);
    // ... which should be invalid (double free)
}

Another one (as requested by jeffz on #gnu):

#include <stdlib.h>

int main(void) {
    for (size_t i = 0; i < 0x7FFFFFFF; ++i) {
        void* ptr = realloc(NULL, 0);
    }
}

According to the man page, this program should not allocate any memory,
but it ends up allocating several gigabytes until OOM killer takes care
of it.

-
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to