# Critique of realloc() wrapper

Seeking code correctness and best practices.

I would like to re-allocate various amounts of memory (0 or more) such that on systems that may return NULL for an allocation of 0 does not falsely imply a memory allocation error.

Given:

• void * (with a valid value or NULL already)
• size_t (new desired size)

• void * (new pointer)
• int (failure status)

#include <assert.h>
#include <stdlib.h>

int ReallocAndTest(char **Buf, size_t NewSize) {
assert(Buf);
char *NewBuf = realloc(*Buf, NewSize);
if ((NewBuf == NULL) && (NewSize > 0)) {
return 1;  // return failure
}
*Buf = NewBuf;
return 0;
}


I came across the below references, which imply a realloc() return of NULL is not always a failure. The lone special case occurs with size is 0. The return value may or may not be NULL.

C11dr 7.22.3.5 The realloc function 4 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.

C11dr §J.1 Unspecified behavior. — The amount of storage allocated by a successful call to the calloc, malloc, or realloc function when 0 bytes was requested (7.22.3).

C11dr §J.3.12 Implementation-defined behavior. Whether the calloc, malloc, and realloc functions return a null pointer or a pointer to an allocated object when the size requested is zero (7.22.3).

1. Use void* rather than char *.

2. With a 0 size, avoid returning the implementation defined
..a) NULL or
..b) ptr that cannot be referenced.
and return a pointer to insure only 1 of the 2 is ever returned.

On point #2, I only slightly favor returning NULL.

• I already see I should be using void * rather than char *. – chux Dec 4 '13 at 21:45
• For semantic consistency, you might want to change 0 to FALSE, 1 to TRUE and int to bool(C++) or bool_t/BOOL/BOOLEAN (or whatever standard bool type you're using in your C program). That will make it more clear to callers what they should expect the function to do. – Matt Dec 8 '13 at 10:00

1. Standard naming convention in C is usually lower_case_with_underscore.

2. You should be using void * rather than char *

3. I would consider making the return value deterministic when the new size is 0 by always returning NULL rather than the implementation defined behaviour (which could technically be a pointer which is not NULL but still not allowed to be dereferenced). free guarantees by spec that free(NULL) is legal.

• I am unfamiliar with the standard in 1. Where may I find it? – chux Dec 5 '13 at 0:09
• – ChrisWue Dec 5 '13 at 6:20
• The wiki says "standard library identifiers are mostly lowercase" and this is not a standard library identifier. Sorry if the "wrapper" description misled. The SO post reflect various conventions but not a standard. The C standard does distinguish between upper and lower case letter in all identifiers, so this implies that upper case usage is not verboten. The SO post did stress consistency. I concur with your naming convention of trying to be standard. – chux Dec 6 '13 at 18:54
• Yes, naming conventions are always subjective. However PascalCase for local variables and function parameters is rather unusual. – ChrisWue Dec 7 '13 at 0:12
• This is a good "patch critique" for the given wrapper. The other answer explains a better wrapper. – Sam Watkins Feb 3 '15 at 12:20

With the variety of behaviors exhibited by different implementations, I think the only safe thing is to test for zero size before the realloc call and set a minimum allocation (eg 1 byte).

Note that realloc will probably set errno to ENOMEM when it fails, but I don't think this is guaranteed.

• ENOMEM appears to be in Linux and not the C standard. It is surprising that a memory allocation error does not generate a error code per the C standard. Maybe a history thing. – chux Dec 5 '13 at 0:15
• +1 Checking for 0 before calling realloc is indeed the correct approach. Avoid writing code that relies on unspecified or impl.defined behavior. One of the point of writing a wrapper is to get rid of such things. – Lundin Dec 10 '13 at 11:53
• I (also) suggest if someone calls your_malloc() or your_realloc() with size 0, you should call malloc() or realloc() with size 1. That way you always have a distinct pointer. Some code may benefit from the assumption that distict allocated objects have distinct addresses; and of course it's not good to be confused between success and failure! I did this in my malloc and realloc wrappers: sam.nipl.net/libb/alloc.b Additionally, this allows your_malloc and your_realloc to be signature compatible with the originals. – Sam Watkins Feb 3 '15 at 12:13