What if NULL and size 0 are passed to realloc()?
Asked Answered
T

3

6

Is the behavior implementation defined? If NULL and size == 0 are passed to realloc():

int main(void)
{
    int *ptr = NULL;

    ptr = realloc(ptr, 0);

    if(ptr == NULL)
    {
        printf("realloc fails.\n");
        goto Exit;
    }

    printf("Happy Scenario.\n");

Exit:
    printf("Inside goto.\n");

return 0;
}

The above code should print "realloc fails", right? But it is not? I've read somewhere that this call to realloc may return NULL also. When does that happen?

Tritheism answered 17/2, 2017 at 16:22 Comment(3)
Possible duplicate of Realloc on NULL-valued (or undefined) pointerNonperishable
The possible duplicate doesn't address the specific point of the behaviour of void *vp = realloc(NULL, 0);.Kries
I agree with @Jonathan here. it looks like the cited dup is missing a discussion of the behavior of realloc'ing for 0 elements, and information about the pointer you would get back. Older Microsoft platforms had a fair of trouble when allocating for 0 elements.Devoe
N
12

This behavior is implementation defined.

From the C standard:

Section 7.22.3.5 (realloc):

3 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 a memory management 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.

So realloc(NULL, 0) is the same as malloc(0)

If we then look at section 7.22.3.4 (malloc):

2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

3 The malloc function returns either a null pointer or a pointer to the allocated space.

The standard does not state what happens when 0 is passed in.

But if you look at the Linux man page:

The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

It explicitly states that the returned value can be freed but is not necessarily NULL.

In contrast, MSDN says:

If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item. Always check the return from malloc, even if the amount of memory requested is small.

So for MSVC, you won't get a NULL pointer.

Naturism answered 17/2, 2017 at 16:37 Comment(2)
Thanks! It was helpful, specifically the contrast with MSDN.Tritheism
"The standard does not state what happens when 0 is passed in." It does, just in the section intro instead of in the realloc paragraph. For C1x, it's under "7.22.3 Memory management functions": "If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object".Bunt
F
12

realloc(3) doc:

If ptr is NULL, then the call is equivalent to malloc(size), for all values of size

malloc(3) doc:

If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be success‐fully passed to free().

So yes, it is implementation defined, you'll either get null or a pointer you can free.

Flouncing answered 17/2, 2017 at 16:24 Comment(4)
If you get a non-null pointer, the pointer you get should be freed to avoid leaks, but cannot be dereferenced (because it provides 0 bytes of legitimately accessible memory).Kries
@JonathanLeffler "... the pointer you get should be freed to avoid leaks" applies to all pointers allocated with 0 or non-zero sizes that do not return NULL. Eventually they should be free'd to avoid leaks. OTOH, if a malloc(0) returns non-NULL, freeing it right away may reduce memory usage and maybe a good idea, but it is not a leak issue.Westonwestover
I wonder what benefit there is, if any, to guaranteeing that a non-null pointer will be unique, rather than simply specifying that each value returned from a zero-sized malloc() , calloc(), or realloc() will be considered distinct for purposes of passing to free() or realloc(), but might happen to compare equal to pointers received from other zero-size operations. It's advantageous not to perform an allocation for a zero-sized allocation request, but having size-zero requests return a pointer to a static dummy object which both free and realloc would ignore...Mauritius
...would make it possible for zero-sized requests to refrain from allocating anything without having to return a null pointer.Mauritius
N
12

This behavior is implementation defined.

From the C standard:

Section 7.22.3.5 (realloc):

3 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 a memory management 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.

So realloc(NULL, 0) is the same as malloc(0)

If we then look at section 7.22.3.4 (malloc):

2 The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

3 The malloc function returns either a null pointer or a pointer to the allocated space.

The standard does not state what happens when 0 is passed in.

But if you look at the Linux man page:

The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

It explicitly states that the returned value can be freed but is not necessarily NULL.

In contrast, MSDN says:

If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item. Always check the return from malloc, even if the amount of memory requested is small.

So for MSVC, you won't get a NULL pointer.

Naturism answered 17/2, 2017 at 16:37 Comment(2)
Thanks! It was helpful, specifically the contrast with MSDN.Tritheism
"The standard does not state what happens when 0 is passed in." It does, just in the section intro instead of in the realloc paragraph. For C1x, it's under "7.22.3 Memory management functions": "If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object".Bunt
D
6

The call

realloc(NULL, size);

is equivalent to

malloc(size);

And what malloc() does when asked to allocate 0 bytes is a bit unclear, the standard doesn't say. I think it's implementation-defined. It basically "doesn't matter"; either it returns NULL, or it returns a pointer where you can legally access zero bytes, those are pretty much alike. Both can be passed to free().

Dysphemism answered 17/2, 2017 at 16:25 Comment(2)
No, don't pass NULL to free() - that is bad practice and could cause a crash depending on the implementation.Scleroma
"If ptr is a null pointer, the function does nothing". Source: cplusplus.com/reference/cstdlib/freeDesai

© 2022 - 2024 — McMap. All rights reserved.