Dynamic arrays: using realloc () without memory leaks

I use realloc to resize allocated memory:

char **get_channel_name(void) { char **result; int n; result = (char **) 0; for (elem = snd_mixer_first_elem(handle), n = 0; elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; if (snd_mixer_selem_has_playback_volume(elem) && snd_mixer_selem_has_playback_switch(elem) && snd_mixer_selem_has_capture_switch(elem)) { if (result == (char **) 0) result = (char **) malloc(sizeof(char *)); else result = (char **) realloc(result, sizeof(char *) * (n + 1)); /* nulled but not freed upon failure */ result[n++] = strdup(snd_mixer_selem_get_name(elem)); } } if (result == (char **) 0) return NULL; result = (char **) realloc(result, sizeof(char *) * (n + 1)); /* nulled but not freed upon failure */ result[n] = NULL; return result; } 

When I check the code using static analysis of the CpCcheck tool code in C / C ++, the following errors are printed:

 Common realloc mistake: 'result' nulled but not freed upon failure 

How can I fix these 2 possible memory leaks?

+5
source share
2 answers

If realloc() fails, it returns NULL .

So, if you do this (and suppose realloc() fails)

 result = realloc(result, ...); 

result will be assigned NULL , and what he pointed out is not free() ed, but the address free() ed is lost.

To fix this, follow these steps:

 void * tmp = realloc(result, ...); if (NULL == tmp) { /* Handle error case, propably freeing what result is pointing to. */ } else { result = tmp; } 
+9
source

The trick to fixing the "nulled but not freed after failure" error is to save the value returned by realloc into a separate pointer and check it for NULL before reassigning the old pointer:

 char **tmp = (char **) realloc(result, sizeof(char *) * (n + 1)); if (tmp) { result = tmp; } else { ... // Handle reallocation error } 

Now that the result assignment is protected with a NULL check, you have the old value to work with: you could free it if you want, or you can continue to use it if you need to. On the other hand, the source code does not give you the same opportunity.

Note. . When you pass a NULL pointer to realloc , it behaves like a malloc . This is why you can refuse a conditional expression when using realloc for the first time - replace this

 if (result == (char **) 0) result = (char **) malloc(sizeof(char *)); else result = (char **) realloc(result, sizeof(char *) * (n + 1)); 

with this:

 char** tmep = (char **) realloc(result, sizeof(char *) * (n + 1)); ... // check temp and assign result here 

Remember to set n to zero - it is currently used uninitialized, which corresponds to undefined.

+3
source

Source: https://habr.com/ru/post/1209651/


All Articles