以下代码用于在 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/