如何修复内存泄漏?

时间:2022-03-14 07:26:02

I have

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

Running this through valgrind returns:

通过valgrind运行它返回:

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

LEAK SUMMARY
still reachable: 120 bytes in 1 blocks

Since I freed everything(stdin, input, buf) why is it still giving me memory leaks? and how do I fix this?

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

1 个解决方案

#1


In a comment, you say that you call exit(0) from your function get_command. A call to exit(x) behaves as if the program returned x from main. That means that you skip the clean-up code at the end of main.

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

In order to fix this, you could return a value from get_command, for example 0 for regular operation, -1 for error or 1 for the end of input. That means that exit(0) in get_command now becomes return 1.

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

Your main loop could then look like:

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

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

Note that I have fixed some other issues with your code:

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

  • Don't use a fixed-size temporary buffer. getline can read lines of arbitrary length. If you copy these to a temporary buffer, at least make sure tat it fits; you've got the len information, after all. It is even better to use the input string directly.
  • 不要使用固定大小的临时缓冲区。 getline可以读取任意长度的行。如果将这些复制到临时缓冲区,至少要确保它适合;毕竟你已经获得了len信息。最好直接使用输入字符串。

  • Don't start with a NULL buffer every time you call getline. This will reduce the number of allocations, because new memory will only be allocated if a line is longer than every line read before, which shouldn't be very often. That also means that the free should go after the loop.
  • 每次调用getline时都不要以NULL缓冲区开头。这将减少分配的数量,因为只有当一条线比之前读取的每条线都长时才会分配新的存储器,这应该不常见。这也意味着免费应该循环之后。

#1


In a comment, you say that you call exit(0) from your function get_command. A call to exit(x) behaves as if the program returned x from main. That means that you skip the clean-up code at the end of main.

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

In order to fix this, you could return a value from get_command, for example 0 for regular operation, -1 for error or 1 for the end of input. That means that exit(0) in get_command now becomes return 1.

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

Your main loop could then look like:

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

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

Note that I have fixed some other issues with your code:

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

  • Don't use a fixed-size temporary buffer. getline can read lines of arbitrary length. If you copy these to a temporary buffer, at least make sure tat it fits; you've got the len information, after all. It is even better to use the input string directly.
  • 不要使用固定大小的临时缓冲区。 getline可以读取任意长度的行。如果将这些复制到临时缓冲区,至少要确保它适合;毕竟你已经获得了len信息。最好直接使用输入字符串。

  • Don't start with a NULL buffer every time you call getline. This will reduce the number of allocations, because new memory will only be allocated if a line is longer than every line read before, which shouldn't be very often. That also means that the free should go after the loop.
  • 每次调用getline时都不要以NULL缓冲区开头。这将减少分配的数量,因为只有当一条线比之前读取的每条线都长时才会分配新的存储器,这应该不常见。这也意味着免费应该循环之后。