What is the best way to zero out new memory after calling realloc while keeping the initially allocated memory intact?
#include
#include <
There is no way to solve this as a general pattern. The reason why is that in order to know what part of the buffer is new you need to know how long the old buffer was. It's not possible to determine this in C and hence prevents a general solution.
However you could write a wrapper like so
void* realloc_zero(void* pBuffer, size_t oldSize, size_t newSize) {
void* pNew = realloc(pBuffer, newSize);
if ( newSize > oldSize && pNew ) {
size_t diff = newSize - oldSize;
void* pStart = ((char*)pNew) + oldSize;
memset(pStart, 0, diff);
}
return pNew;
}
First of all, realloc can fail, so you need to check for NULL. Second, there is no better way to zero out the memory: just memset from the end of the old buffer to the end of the larger buffer.
There is probably no need to do the memset
: you may not be using colors[k]
before setting it with something valid later. For example, your code sets colors[i]
to a newly allocated color
pointer, so you didn't need to set colors[i]
to NULL
.
But, even if you wanted to "zero it out so everything is nice", or really need the new pointers to be NULL
: the C standard doesn't guarantee that all-bits-zero is the null pointer constant (i.e., NULL
), so memset()
isn't the right solution anyway.
The only portable thing you can do is to set each pointer to NULL
in a loop:
size_t k;
for (k=COLORCOUNT; k < i+1; ++k) /* see below for why i+1 */
colors[k] = NULL;
Your primary problem is that your realloc()
call is wrong. realloc()
returns a pointer to the resized memory, it doesn't (necessarily) resize it in-place.
So, you should do:
/* i+1 because you later assign to colors[i] */
rgb_t **tmp = realloc(colors, (i+1) * sizeof *tmp);
if (tmp != NULL) {
/* realloc succeeded, can't use colors anymore */
colors = tmp;
} else {
/* realloc failed, colors is still valid */
}
If you really want to know what the memset()
call should be, you need to set to zero the memory starting at colors+COLORCOUNT
, and set i+1-COLORCOUNT
members to zero:
memset(colors+COLORCOUNT, 0, (i+1-COLORCOUNT) * sizeof *colors);
But as I said above, all bytes zero is not guaranteed to be a NULL
pointer, so your memset()
is useless anyway. You have to use a loop if you want NULL
pointers.
Write your own function, say reallocz
, that accepts the current size as a parameter, and calls realloc
and memset
for you. It really won't get much better than what you already have... it's C, after all.