对于以下代码: (1) "main"调用函数"f1" . (2) 函数"f1"做了一些数字处理;使用malloc创建一个"char"数组,然后将数组的指针返回给main(不分配-freeing-数组) .
我有3个与案例有关的问题: (1) 我假设,虽然函数"f1"已经终止,但分配的char数组仍然保持分配状态,直到主程序完全终止 . 也就是说,分配的内存仍然属于主内存,没有其他进程可以从外部访问(我的意思是,干扰)它 . 我对吗? (2) 我是否必须在程序终止之前释放阵列(在"f1"中分配)(或者在主程序终止后立即释放)? (3) 如果第二个问题的答案是"yes"那么你如何释放另一个函数中分配的数组?
注意:我想保持在纯粹的c的范围内,而不是溢出到c .
char *f1 (...) {
...
...
char *fTmp = malloc (length1 * sizeof (char));
char *fData = malloc (length2 * sizeof (char));
...
...
free (fTmp);
return (fData);
}
int main () {
char *fData = f1 (...);
...
return (0);
}
7 回答
真正 . 动态分配的内存与函数无关,它属于进程 .
内存不属于
main()
(用作函数),而是处理自身(其中main()
只是入口点) . 在具有内存保护的系统中(每个进程与其他进程隔离),无法从外部访问 . 但是,您可以以特定于系统的方式分配它,以跨进程共享内存 .是 . 未分配的内存 - in most systems - 在进程终止时由操作系统自动释放,但这取决于系统 . IMO甚至在操作系统执行时你应该总是解除分配,使用这种自动释放作为红旗(我忘记了解除分配,这是一个错误吗?我错过了什么?) . 此外,如果
f1
被调用1000次,那么每次快速吃掉所有可用内存都会泄漏内存 . 想想服务器中的进程,它可能(并且应该)启动并运行多年 .它's nice when who allocates memory also frees it. If it'不可能,然后调用者将负责这样的内存 . 例如,
strdup()
的作用 . 在这种情况下,被调用的函数必须返回(以某种方式)指向已分配内存的指针(或可由另一个专用函数使用的句柄/令牌) . 例如:请注意,如果要隐藏此类内部指针,有许多技术 . 您可以使用标记(例如,整数,字典中的键),
typedef
或不透明类型 .是的,分配有
malloc()
的内存一直保留,直到被释放 . 函数如何才能将可变大小的数据返回给调用者?程序退出时,将释放分配有
malloc()
的所有内存 . 但是,在程序终止之前保留大量不需要的内存通常不是一个好主意,因为它会影响性能,或者系统可能耗尽虚拟内存 . 对于长时间运行的程序,这可能是一个特别关注的问题,它们的内存使用有时会持续增长,直到它们使用所有可用的虚拟内存 .您在函数返回的指针上调用
free()
. 所以在你的情况下,main()
在使用数组完成后可以做free(fData)
.这应该都包含在任何C编程类或教科书中 .
malloc
在堆上分配内存,因此这个内存保持分配状态,直到它被free
函数释放或程序终止成功 .在您的情况下,您在
f1
中释放了ftemp
,因此在函数终止后它不再存在 .fdata
仍然在堆上,当您返回指向该分配位置的指针时,main
可以访问它 .一旦
main
成功终止,fdata
指向的内存将被释放 .所以,只要你不再需要它就可以释放内存 . 在程序结束时释放块是没有意义的,因为全部当进程终止时(考虑到现代操作系统),程序的空间将返回给系统 .
是的,它还在堆里 . 但是,您对流程的概念感到困惑 . 除非你创建另一个进程(在* nix上使用
fork
),否则它仍然是相同的进程 .在不使用时释放内存是个好习惯 . 但是如果程序正常终止,系统将释放分配的内存 .
喜欢这个:
使用
malloc
将在堆上分配内存,直到它free
它 .这意味着您需要确保每个malloc都有相应的免费,也并不意味着没有其他进程无法访问您的数据 . 它只是一个地址的值 .
在你的主要你必须
free(fData)
以避免内存泄漏 .To sum up then:
1)你的第一个假设是正确的,第二个和第三个假设是正确的 . 它将保持分配状态,但它不是主要的本地,并且在它终止时不受该进程的约束 .
2)是的,你必须释放它
3)使用从函数中获得的指针 . 如果没有从函数返回指向已分配数据的指针,请确保函数
free
s .在C中可以使用两种基本类型的内存 . 两种类型是堆栈和堆 . 通常,在函数中创建的变量将在堆栈上分配,并在函数返回时释放 . 堆中分配的内存将保持不变,您有义务在程序中管理该分配 . 堆中的内存将保持分配状态,直到您使用引用数据块的指针(内存地址)释放为止 .
对它们进行一点阅读将有助于您理解 . 我要指出你有两个fData实例,每个实例都有自己的范围 . 两个指针都指向您分配的内存:
..即使它们在代码执行时传入和传出范围 .
如果你没有使用,最终会累积 - 如果你用许多其他指针完成此操作 - 你的程序可能会耗尽内存 . 在使用
free
函数释放内存块之后,我还建议将NULL
分配给指针,因为这可以防止悬空指针,即使你已经释放了一个指针,如果你尝试访问它,你可能会得到未定义的行为,而访问对NULL
指针的操作导致崩溃,因此您可以轻松地跟踪问题