【问题标题】:How do I fix my memory leak?如何修复我的内存泄漏?
【发布时间】:2015-05-03 12:00:46
【问题描述】:

我有

int main(void){
  while (1){
    char *input = NULL;
    char buf[1000];
    int read;
    size_t len;
    read = getline(&input, &len, stdin);

    if (-1 != read){
      sprintf(buf, "%s", input);
      lowercase(buf);; // custom function
      get_command(buf); // custom function already checked for memory leak
    }
    free(stdin);
    free(input);
    free(buf);
  }
  return 0;
}

通过 valgrind 运行它返回:

HEAP SUMMARY
by 0x4022c2: main(prog.c:647) //  read = getline(&input, &len, stdin);

LEAK SUMMARY
still reachable: 120 bytes in 1 blocks

既然我释放了所有东西(stdin、input、buf),为什么它仍然给我内存泄漏?我该如何解决这个问题?

【问题讨论】:

  • 删除free(stdin);和free(buf);
  • 所有这些free()s,而不是malloc()!你真的需要回到书本上——这段代码有很多问题!
  • 并为input分配内存。
  • 我是你展示的代码,你不会跳出循环。你是来自get_command 的某个地方的exit() 吗?在这种情况下,您将绕过free(input)。
  • getline 的优点是它会读取任意长度的行并为其分配足够的内存。使用临时固定大小的缓冲区buf 会失去这种优势。如果你有很长的行,buf 可能会溢出。 (当然,1000 个字符已经足够了,为什么还要冒这个险?只需小写 input 并将其传递给 get_command。)

标签: c memory-management memory-leaks


【解决方案1】:

在评论中,您说您从函数get_command 调用exit(0)。对exit(x) 的调用就像程序从main 返回x 一样。这意味着您跳过了main 末尾的清理代码。

为了解决这个问题,您可以从get_command 返回一个值,例如,0 表示常规操作,-1 表示错误或 1 表示输入结束。这意味着get_command 中的exit(0) 现在变为return 1。

您的 main 循环可能如下所示:

int main(void)
{
    char *input = NULL;
    size_t len = 0;

    while (1) {
        if (getline(&input, &len, stdin) < 0) break;

        lowercase(input);
        if (get_command(input) == 1) break;
    }

    free(input);

    return 0;
}

请注意,我已经修复了您的代码的其他一些问题:

  • 不要使用固定大小的临时缓冲区。 getline 可以读取任意长度的行。如果您将这些复制到临时缓冲区,至少要确保它适合;毕竟,您已经获得了len 信息。直接使用input 字符串会更好。
  • 不要在每次调用getline 时都从NULL 缓冲区开始。这将减少分配的数量,因为只有当一行比之前读取的每一行都长时才会分配新内存,这种情况不应该经常发生。这也意味着free 应该在循环之后。

【讨论】:

  • 我花了很长时间阅读和查看您的代码来理解它,但它帮助了我!谢谢!
  • 为什么花了你这么长时间?因为我已经在if 的条件部分中调用了getline 和get_command?如果您对临时变量感觉更舒服,当然可以使用它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
  • 2018-05-09
  • 2018-07-12
  • 2012-09-14
  • 2020-05-24
相关资源
最近更新 更多