【问题标题】:realloc - memory leakrealloc - 内存泄漏
【发布时间】:2011-03-17 12:55:17
【问题描述】:

我有一些 C 代码:

typedef struct {
    size_t len;
    size_t alloclen;
    char *buf;
} str;

void strnappnd(str **s, const char *buf, size_t n) {

    if ((*s)->len + n >= (*s)->alloclen) {
        size_t nalloclen = (*s)->len + n + 1;
        void *tmp = realloc((*s)->buf, nalloclen);
        if (!tmp) {
            printf("failure");
            exit(-1);
        }
        (*s)->buf = tmp;
        (*s)->alloclen = nalloclen;
    }
    memccpy((*s)->buf + (*s)->len, buf, '\0', n);
    (*s)->len += n;
    (*s)->buf[(*s)->len] = '\0';
}

void strfree(str **s) {
    free((*s)->buf);
    free(*s);
    *s = NULL;
}

显然,strnappnd 在 realloc 行泄漏。为什么?

【问题讨论】:

  • @user282635 在最终重新分配之后,您最终释放了(*s)->buf 吗?
  • @aix:我认为使用 realloc 意味着您不需要释放缓冲区。
  • 您如何检测泄漏?
  • 重要的是当已经有足够的空间时不追加字符串。
  • 三点:1)函数名不能以“str”开头,这是保留的命名空间; 2)考虑将缓冲区增加超过 1 个字节,如果这是出于通用目的,则可以更好地摊销多个附加的成本; 3) 正如@pmg 所说,对于缓冲区足够大的情况,似乎缺少代码。将其从 realloc() 路径中分解出来。

标签: c memory-management realloc


【解决方案1】:

考虑:

void f() {
  str *s = (str *)malloc(sizeof(str));
  s->len = 5;
  s->alloclen = 5;
  s->buf = strdup("Hello");
  strnappend(&s, " World!", 7);
  free(s); /* courtesy of Eric */
}

如果你有类似的情况,realloc() 分配的内存会泄漏,因为f() 被留下。

【讨论】:

  • 还有malloc()分配的内存。
  • 我认为一个更好的例子是在堆栈上分配str 的实例。
  • @Erik:我认为就内存检查器而言,malloc() 调用分配的内存将与realloc() 调用相关联。所以从技术上讲,就内存检查器而言,只有realloc() 泄漏(再次,我只是在猜测)。我相信这是因为realloc() 可能由于内存碎片而无法扩展已分配的内存块的大小。相反,它可能必须释放内存并分配请求大小的全新块。
  • @Frerich:我说的是你第一行中的 malloc :)
  • @Frerich:不,realloc 是在 s->buf 而不是 s 本身上调用的。
【解决方案2】:

如果你写了

(*s)->buf = realloc((*s)->buf, nalloclen)

这将是内存泄漏,因为如果realloc 失败并返回NULL,您将丢失仍然指向已分配内存的(*s)->buf 指针。

由于您在失败时退出,这不是问题,但您的静态分析器可能会忽略exit

【讨论】:

  • @user282635 – 是什么告诉您realloc 泄漏?某种静态分析器?瓦尔格林?
  • 不,我在循环中运行代码(几乎就是我发布的内容)并且内存使用量越来越大......
  • @user282635 - 您应该发布程序的其余部分,因为这两个函数中的内存处理看起来不错。
【解决方案3】:

就像这个 mtrace 所说的“没有内存泄漏”

char *strnappnd(str **s, const char *buf, size_t n) {
    ...
    return (*s)->buf;
}
void strfree(str *s){
    free(s->buf);
    free(s);
}

使用 Frerich 给出的示例代码

void f() {
  str *s = (str *)malloc(sizeof(str));
  s->len = 5;
  s->alloclen = 5;
  s->buf = strdup("Hello");
  s->buf = strnappend(&s, " World!", 7);
  strfree(s);
}

【讨论】:

    【解决方案4】:

    您创建了 strfree() 函数,但它没有在代码中使用。 如果不使用,内存需要始终处于空闲状态。

    if (!tmp) {
        printf("failure");
        if (!(*s) && !((*s)->buf))
           strfree(&(*s));
        exit(-1);
    }
    

    查看 strfree(),看起来你在某处也为 *s 保留了内存。 在你的代码完成之前做同样的事情。

    if (!(*s) && !((*s)->buf))
       strfree(&(*s));
    

    【讨论】:

      猜你喜欢
      • 2011-05-31
      • 1970-01-01
      • 2015-05-09
      • 1970-01-01
      • 2020-09-19
      • 2015-02-19
      • 2018-03-23
      • 2020-11-09
      • 1970-01-01
      相关资源
      最近更新 更多