动态数组:使用realloc()而不会出现内存泄漏

时间:2014-12-21 13:33:10

标签: c realloc cppcheck

我使用realloc来调整分配的内存:

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;
}

当我用cppcheck工具检查代码静态C / C ++代码分析时,打印出以下警告:

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

如何修复这2个可能的内存泄漏?

2 个答案:

答案 0 :(得分:9)

如果realloc()失败,则返回NULL

所以,如果你这样做(假设realloc()会失败)

result = realloc(result, ...);

result将被分配NULL,其指向的内容不是free(),且free()的地址将丢失。

要解决此问题,请执行以下操作:

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

答案 1 :(得分:3)

修复“已失效但未失败”错误的技巧是将realloc返回的值存储到单独的指针中,并在重新分配旧指针之前检查NULL:< / p>

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

现在result的分配受到NULL检查的保护,您可以使用旧值:如果您愿意,可以free,或者您可以继续使用它如果你需要。另一方面,原始代码没有给你相同的选项。

注意:当您将NULL指针传递给realloc时,其行为类似于malloc。这就是为什么你可以在第一次使用realloc时放弃条件 - 替换这个

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

用这个:

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

不要忘记将n设置为零 - 目前,它是未初始化的,这是未定义的行为。