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

Posted

技术标签:

【中文标题】释放返回变量内存的正确方法【英文标题】:Proper Way to Free Memory of a Returned Variable 【发布时间】:2015-06-21 16:46:08 【问题描述】:

我创建了一个旨在获取用户输入的函数。它要求将内存分配给保存用户输入的变量;但是,该变量在函数末尾返回。释放分配的内存/返回变量值的正确方法是什么?

代码如下:

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还是调用者。相关的,如果在您的目标平台上受支持,getline,一个添加到 POSIX.1-2008 的库函数,似乎几乎做你想要实现的事情。它仍然需要调用者最终free 任何返回的分配,但还提供重用语义,您的代码。根据预期用途和目标平台,可能值得考虑。 【参考方案1】:

很简单,只要将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()返回的指针。

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

    您正在为MAX_SIZE chars 分配空间,因此您应该乘以sizeof(char),即1,而不是sizeof(char *),后者将分配MAX_SIZE 指针,您还可以使MAX_SIZE 改为函数参数,因为如果要分配固定缓冲区,则可以在 main() 中定义大小为 MAX_SIZE 的数组,如 char input[MAX_SIZE],并将其作为参数传递给 readInput(),从而避免 @ 987654338@和free()

    您分配了那么多空间,但您没有防止 while 循环中的溢出,您应该验证 i &lt; MAX_SIZE

【讨论】:

他不能使用本地数组,因为当它返回并且函数的堆栈帧被破坏时,无法保证数组完好无损。编译器会给你一个警告:“函数返回局部变量的地址 [-Wreturn-local-addr]”。除此之外,很好的答案。 @EnzoFerber 我的意思是将数组传递给函数并在那里填充,我知道你不能返回本地数组。我想我需要澄清一下。 很好的例子。谢谢。【参考方案2】:

您可以编写一个返回类型为char* 的函数,返回input,并要求用户在处理完数据后调用free

您也可以要求用户自己传入一个适当大小的缓冲区,连同缓冲区大小限制,并返回写入缓冲区的字符数。

【讨论】:

【参考方案3】:

这是一个经典的 c 案例。函数 malloc 为其结果分配内存,调用者必须释放返回值。您现在正走在c 内存泄漏的薄冰上。 2 个原因

首先;您无法以可执行的方式传达免费要求(即编译器或运行时无法帮助您 - 与指定参数类型相比)。您只需在某处记录它并希望调用者已阅读您的文档

第二:即使调用者知道释放结果他可能会犯错误,也会采取一些不释放内存的错误路径。这不会立即导致错误,似乎一切正常,但运行 3 周后,您的应用在内存不足后崩溃

这就是为什么这么多“现代”语言都关注这个主题的原因,c++ 智能指针、Java、C# 等垃圾回收......

【讨论】:

以上是关于释放返回变量内存的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中释放内存的正确方法是啥

在c ++中删除和释放向量内存的正确方法(防止不同的内存相关错误)

共享内存实现上的 C++ 内存池:这种分配和释放方法是不是正确?

Three.js Collada - dispose() 和释放内存(垃圾收集)的正确方法是啥?

如果程序因错误而提前退出,那么释放动态分配的内存的正确方法是啥?

Objective-C 自动释放内存管理