【问题标题】:Dynamic arrays: using realloc() without memory leaks动态数组:使用 realloc() 没有内存泄漏
【发布时间】:2015-02-19 19:03:42
【问题描述】:

我使用 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

如何解决这两种可能的内存泄漏?

【问题讨论】:

    标签: c realloc cppcheck


    【解决方案1】:

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

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

    result = realloc(result, ...);
    

    result 将被分配NULL 并且它指向的不是free()ed 并且free()ed 的地址丢失了。

    要解决这个问题:

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

    【讨论】:

      【解决方案2】:

      修复“nulled but not freed after failure”错误的技巧是将realloc返回的值存储到一个单独的指针中,并在重新分配旧指针之前检查它是否有NULL:

      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 设置为零 - 目前,它未初始化,这是未定义的行为。

      【讨论】:

        猜你喜欢
        • 2011-05-31
        • 1970-01-01
        • 1970-01-01
        • 2016-08-29
        • 1970-01-01
        • 2015-05-09
        • 2020-09-19
        • 2022-01-13
        • 1970-01-01
        相关资源
        最近更新 更多