释放返回变量内存的正确方法
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
char
s 分配空间,因此您应该乘以sizeof(char)
,即1
,而不是sizeof(char *)
,后者将分配MAX_SIZE
指针,您还可以使MAX_SIZE
改为函数参数,因为如果要分配固定缓冲区,则可以在 main()
中定义大小为 MAX_SIZE
的数组,如 char input[MAX_SIZE]
,并将其作为参数传递给 readInput()
,从而避免 @ 987654338@和free()
。
您分配了那么多空间,但您没有防止 while
循环中的溢出,您应该验证 i < MAX_SIZE
。
【讨论】:
他不能使用本地数组,因为当它返回并且函数的堆栈帧被破坏时,无法保证数组完好无损。编译器会给你一个警告:“函数返回局部变量的地址 [-Wreturn-local-addr]”。除此之外,很好的答案。 @EnzoFerber 我的意思是将数组传递给函数并在那里填充,我知道你不能返回本地数组。我想我需要澄清一下。 很好的例子。谢谢。【参考方案2】:您可以编写一个返回类型为char*
的函数,返回input
,并要求用户在处理完数据后调用free
。
您也可以要求用户自己传入一个适当大小的缓冲区,连同缓冲区大小限制,并返回写入缓冲区的字符数。
【讨论】:
【参考方案3】:这是一个经典的 c 案例。函数 malloc 为其结果分配内存,调用者必须释放返回值。您现在正走在c 内存泄漏的薄冰上。 2 个原因
首先;您无法以可执行的方式传达免费要求(即编译器或运行时无法帮助您 - 与指定参数类型相比)。您只需在某处记录它并希望调用者已阅读您的文档
第二:即使调用者知道释放结果他可能会犯错误,也会采取一些不释放内存的错误路径。这不会立即导致错误,似乎一切正常,但运行 3 周后,您的应用在内存不足后崩溃
这就是为什么这么多“现代”语言都关注这个主题的原因,c++ 智能指针、Java、C# 等垃圾回收......
【讨论】:
以上是关于释放返回变量内存的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
在c ++中删除和释放向量内存的正确方法(防止不同的内存相关错误)
共享内存实现上的 C++ 内存池:这种分配和释放方法是不是正确?
Three.js Collada - dispose() 和释放内存(垃圾收集)的正确方法是啥?