c - 此函数中缺少 free() 导致内存泄漏

标签 c free dynamic-memory-allocation

以下代码用于在 c 中查找基本 shell 的可执行文件的路径。如您所见,我动态分配了 path 变量,然后检查路径是否存在(通过辅助函数 cmd_exists 中的 lstat) .然后我返回路径变量。我的问题是,这会导致内存泄漏,因为 path 永远不会被释放。在我返回它的值之前我无法释放路径,并且截至目前我想不出任何方法来释放已分配的内存。如果有人可以帮助我,我将不胜感激。谢谢

char * find_path(char * mypath, char * command){
     char * token = strtok(mypath, "#");
     while(token != NULL){
                         /*token size + 1 (for /) + command size*/
          char * path = calloc(strlen(token)+1+strlen(command)+1, sizeof(char));
          strcat(path, token);
          strcat(path, "/");
          strcat(path, command);
          if(cmd_exists(path) == 1){
             return path;
          }
          token = strtok(NULL, "#");
     }
     return NULL;
}

最佳答案

这确实是 C 的问题之一。内存所有权可能非常困难,因为 C++ 中没有 RAII 概念(本质上,没有自动析构函数)。

我看到 3 个解决方案如何解决这个问题:

  • 3 中最糟糕的解决方案是拥有一个全局静态缓冲区,并让您的 find_path 函数填充此缓冲区并将指向它的指针返回给调用者。这个技巧被很多其他标准的 C 函数使用,但它也有很多问题(通常不是线程安全的,如果它是线程安全的,那么下一次调用可能会覆盖以前的返回值)。参见 https://en.cppreference.com/w/cpp/utility/program/getenv对于具有此行为的函数(查看顶部的警告)。
  • 稍微好一点的解决方案是记录函数的返回值,并清楚地告诉调用者释放返回的指针是他的责任。如果他不这样做,你就会发生内存泄漏。参见 https://en.cppreference.com/w/c/experimental/dynamic/strdup对于使用此行为的函数。
  • 另一种解决方案是让调用者将最大大小的缓冲区传递给您的函数。因此,不是返回 char *,而是添加 char *size_t 参数(size_t 表示char * 字符缓冲区)。然后你的 find_path 函数可以填充这个缓冲区。参见 https://en.cppreference.com/w/cpp/string/byte/strncpy对于具有此行为的函数。这种方法的问题是,如果缓冲区不够大,您的函数需要返回一个失败,调用者必须传递一个更大的缓冲区。一些 Windows 函数通过让函数返回一个“预期的”缓冲区大小来解决这个问题,所以如果调用失败(因为缓冲区不够大),调用者可以使用返回值来查看缓冲区应该有多大,并分配更大的缓冲区。

我的首选解决方案取决于实际情况。如果存在有意义的最大缓冲区大小(例如最大文件路径),我会采用第三种选择。我会采取第二种选择是最大缓冲区大小很难预测。无论如何,我绝不会使用第一种选择。

关于c - 此函数中缺少 free() 导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54920302/

相关文章:

c - 如何从字符串中删除括号?

c - 学习 C 试图通过函数找出这个 malloc 的东西

c - 如果我想捕获我在 fun1 的正式参数中传递的值,我该怎么做?

如果我想销毁链表并释放内存,我不能直接输入 head=NULL 吗?

c - 我试图将一个字符串解析为不同的单词,稍后尝试释放它们,但其中 2 个字符串具有相同的字节地址

c - 在数组上使用 malloc

C++:派生类对象被析构时释放动态内存

c - "lvalue required in asm statement"错误

c - 释放导致崩溃

c++ - 删除 char 数组似乎根本不会影响数组