I have been writing code where data are allocated in many loops, and found using realloc()
quite convenient for the purpose because it handles initial and mid-loop data consistently without adding conditions for freeing and allocating new pointers.
I wrote this little test program:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char *x = NULL;
x = realloc (x, 0);
printf ("Address of realloc (NULL, 0): %p\n", x);
assert (x != NULL);
printf ("Address of realloc (x, 8): %p\n", x);
x = realloc (x, 8);
assert (x != NULL);
x = realloc (x, 0);
assert (x == NULL);
printf ("Address of realloc (x, 0): %p\n", x);
x = realloc (x, 21);
printf ("Address of realloc (x, 21): %p\n", x);
assert (x != NULL);
x = realloc (x, 0); // free.
assert (x == NULL);
printf ("Address of realloc (x, 0): %p\n", x);
return 0;
}
And doing a memory check:
$ gcc -Wall -g test_realloc.c -o test_realloc.o
$ valgrind ./test_realloc.o
==1192613== Memcheck, a memory error detector
==1192613== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1192613== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==1192613== Command: ./test_realloc.o
==1192613==
Address of realloc (NULL, 0): 0x4a3a040
Address of realloc (x, 8): 0x4a3a040
Address of realloc (x, 0): (nil)
Address of realloc (x, 21): 0x4a3a510
Address of realloc (x, 0): (nil)
==1192613==
==1192613== HEAP SUMMARY:
==1192613== in use at exit: 0 bytes in 0 blocks
==1192613== total heap usage: 4 allocs, 4 frees, 1,053 bytes allocated
==1192613==
==1192613== All heap blocks were freed -- no leaks are possible
==1192613==
==1192613== For lists of detected and suppressed errors, rerun with: -s
==1192613== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
So far, great. The only caveat is that the initial value must be initialized (even to NULL
).
Now I am wondering how portable this is across platforms. man 3 realloc
on Linux x86_64 is pretty explicit about this behavior except for realloc (NULL, 0)
which in this case, unexpectedly yields a non-NULL address.
How far can I rely on this behavior?
EDIT: Precisely, my question is whether I can rely on my sample program to be free of UB or memory leaks on any platform.
Thanks.