Search code examples
crealloccppcheck

Dynamic arrays: using realloc() without memory leaks


I use realloc to resize the memory allocated:

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 code with cppcheck tool static C/C++ code analysis, printed the following warings:

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

How can I fix these 2 possible memory leaks?


Solution

  • If realloc() fails it returns NULL.

    So if you do (and assuming realloc() would fail)

    result = realloc(result, ...);
    

    result will be assigned NULL and what it pointed to is not free()ed and the address to be free()ed is lost.

    To fix this do:

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