How to reset new memory after realloc

What is the best way to reset new memory after calling realloc while preserving the originally saved memory?

#include <stdlib.h> #include <assert.h> #include <string.h> #include <stdio.h> size_t COLORCOUNT = 4; typedef struct rgb_t { int r; int g; int b; } rgb_t; rgb_t** colors; void addColor(size_t i, int r, int g, int b) { rgb_t* color; if (i >= COLORCOUNT) { // new memory wont be NULL colors = realloc(colors, sizeof(rgb_t*) * i); //something messy like this... //memset(colors[COLORCOUNT-1],0 ,sizeof(rgb_t*) * (i - COLORCOUNT - 1)); // ...or just do this (EDIT) for (j=COLORCOUNT; j<i; j++) { colors[j] = NULL; } COLORCOUNT = i; } color = malloc(sizeof(rgb_t)); color->r = r; color->g = g; color->b = b; colors[i] = color; } void freeColors() { size_t i; for (i=0; i<COLORCOUNT; i++) { printf("%x\n", colors[i]); // can't do this if memory isn't NULL // if (colors[i]) // free(colors[i]); } } int main() { colors = malloc(sizeof(rgb_t*) * COLORCOUNT); memset(colors,0,sizeof(rgb_t*) * COLORCOUNT); addColor(0, 255, 0, 0); addColor(3, 255, 255, 0); addColor(7, 0, 255, 0); freeColors(); getchar(); } 
+6
c memory-management null
source share
4 answers

There is probably no need to do a memset : you cannot use colors[k] before setting it with something valid later. For example, your code sets colors[i] to the highlighted highlighted color pointer, so you don't need to set colors[i] to NULL .

But even if you want to โ€œzero it out so that everything is fine,โ€ or you really need the new pointers to be NULL : the C standard does not guarantee that all-bits-zero is a constant of a null pointer (i.e. NULL ), so memset() in any case is not the right decision.

The only portable thing you can do is 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; 

The main problem is that your call to realloc() incorrect. realloc() returns a pointer to the modified memory; it (optionally) does not change its size.

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 zero memory starting with colors+COLORCOUNT and set the i+1-COLORCOUNT members to zero:

 memset(colors+COLORCOUNT, 0, (i+1-COLORCOUNT) * sizeof *colors); 

But, as I said above, all 0 bytes are not guaranteed to be a NULL pointer, so your memset() useless. You should use a loop if you want NULL pointers.

+4
source share

It is not possible to solve this problem as a common template. The reason is that in order to find out which part of the buffer is new, you need to know how long the old buffer has been. It is impossible to define this in C and therefore prevent a general solution.

However, you can write a wrapper, for example,

 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; } 
+6
source share

First of all, realloc may fail, so you need to check for NULL. Secondly, there is no better way to reset memory: just memset from the end of the old buffer to the end of the larger buffer.

+3
source share

Write your own function, say reallocz , which takes the current size as a parameter and calls realloc and memset for you. It really won't be much better than what you already have ... it's C, after all.

+1
source share

All Articles