7

我使用 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 个可能的内存泄漏?

4

2 回答 2

13

如果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;
  }
}
于 2014-12-21T13:37:53.073 回答
3

修复“空但未在失败时释放”错误的技巧是将返回的值存储到一个单独的指针中,并在重新分配旧指针之前realloc检查它:NULL

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

既然分配resultNULL检查保护,您就可以使用旧值: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为零 - 目前,它未初始化,这是未定义的行为。

于 2014-12-21T13:39:04.007 回答