正确的方法释放已返回变量的内存

36

我创建了一个函数来获取用户输入。它要求为包含用户输入的变量分配内存;然而,该变量在函数结束时被返回。正确的方法是什么,以释放已分配的内存/返回变量的值?

以下是代码:

char *input = malloc(MAX_SIZE*sizeof(char*));
int i = 0;
char c;

while((c = getchar()) != '\n' && c != EOF) {
    input[i++] = c;
}

return input;

我应该返回输入变量的地址并在使用后释放它吗?

想知道最合适的方法来释放输入变量。


如果你使用了malloc,最终会有人需要free,无论是你在另一个API中还是调用者。相关的,如果你的目标平台支持,在POSIX.1-2008中添加的库函数getline似乎可以几乎实现你想要实现的功能。它仍然需要调用者最终free任何返回的分配,但也提供了重用语义,而你的代码则没有。根据预期的使用和目标平台,考虑使用它可能是值得的。 - WhozCraig
3个回答

30

很简单,只要你把malloc()返回的指针传递给free(),就可以了。

例如:

char *readInput(size_t size)
 {
    char *input;
    int   chr;
    input = malloc(size + 1);
    if (input == NULL)
        return NULL;
    while ((i < size) && ((chr = getchar()) != '\n') && (chr != EOF))
        input[i++] = chr;
    input[size] = '\0'; /* nul terminate the array, so it can be a string */
    return input;
 }

 int main(void)
  {
     char *input;
     input = readInput(100);
     if (input == NULL)
         return -1;
     printf("input: %s\n", input);
     /* now you can free it */
     free(input);
     return 0;
  }

你永远不应该做的事情就是像这样

free(input + n);

因为input + n不是由malloc()返回的指针。

但您的代码还有其他问题需要注意。

  1. 您正在为 MAX_SIZE char分配空间,因此应该乘以sizeof(char),其值为1,而不是sizeof(char *),这将分配MAX_SIZE个指针。同时,您可以将MAX_SIZE作为函数参数传递,因为如果您正在分配固定缓冲区,则可以在main()中定义大小为MAX_SIZE的数组,如char input[MAX_SIZE],并将其作为参数传递给readInput(),从而避免使用malloc()free()

  2. 您正在分配大量空间,但在while循环中没有防止溢出,应该验证i < MAX_SIZE


他不能使用本地数组,因为当它返回并且函数的堆栈帧被销毁时,将无法保证数组完整。编译器会给出警告:"function returns address of local variable [-Wreturn-local-addr]"。除此之外,回答很好。 - Enzo Ferber
1
@EnzoFerber 我的意思是将数组传递到函数中并在函数内部填充它,我知道你不能返回本地数组。我认为我需要澄清这一点。 - Iharob Al Asimi
1
好的例子。谢谢。 - George

6
你可以编写一个返回类型为char*的函数,返回input,并要求用户在使用数据后调用free来释放内存。
你也可以要求用户自行传入正确大小的缓冲区和缓冲区大小限制,并返回写入缓冲区的字符数。

6

这是一个经典的C语言案例。一个函数为其结果分配内存,调用者必须释放返回的值。你现在正在涉足C语言内存泄漏的危险领域。原因有两个:

第一个原因:你无法通过可执行的方式来告诉编译器或运行时需要释放分配的内存(与指定参数类型相比)。你只能在某个地方记录下这个要求,希望调用者已经阅读了你的文档。

第二个原因:即使调用者知道要释放结果,他可能会犯错误,在某些错误路径上没有释放内存。这不会立即引起错误,看起来一切正常,但在运行3周后,你的应用程序会因为内存耗尽而崩溃。

这就是为什么许多“现代”语言都专注于这个主题,比如C++智能指针,Java、C#等垃圾回收机制...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接