为什么我在声明指针时必须使用free():
int *temp = (int*)malloc(sizeof(int)) *temp = 3;
但不是我这样做的时候:
int temp = 3;
Alnitak.. 27
正常声明放在堆栈上.当函数返回时,堆栈指针恢复到调用函数之前的值,因此内存会自动回收.
基于Malloc的声明是从"堆"分配的,这需要程序员管理分配和解除分配.
正常声明放在堆栈上.当函数返回时,堆栈指针恢复到调用函数之前的值,因此内存会自动回收.
基于Malloc的声明是从"堆"分配的,这需要程序员管理分配和解除分配.
你不必总是在指针上使用free,只需使用malloc声明的指针.您可以声明指向堆栈上的内存位置的指针
int a = 3; int* p = &a;
当内存超出范围时,此内存(以及指针)也将自动处理掉.使用malloc在堆上分配相同的内存,因此您必须手动处理清理.
因为语言允许您在堆栈和堆之间进行选择.
您想要在堆栈和堆之间进行选择的原因:
堆上的变量故意不释放自己,以便您可以使用它们超出代码块或函数的范围.
与堆相比,使用堆栈更有效
在大多数编译器中,您无法在运行时选择堆栈上的对象或数组的大小,因此将在此处使用堆.
为什么无法自动释放堆:
因为没有办法知道你何时完成了记忆.有一些方法可以模拟垃圾收集,但这涉及到堆栈上没有更多变量并且堆上有一个指向堆上数据的指针.
更多关于Stack vs Heap:
C语言让您选择是否要在堆栈或堆上定义变量.
堆栈上的变量在超出范围时会自动释放.
堆上的变量不会自动释放.
malloc在堆上创建变量.一个简单的声明,如int x; 在堆栈上创建一个变量.
请参阅我的答案中的堆栈与堆的进一步阅读.
指针:
只是为了澄清:指针变量是在堆栈上创建的,它们为堆上分配的数据保存一个内存地址.它们在32位系统上的堆栈上占用4个字节,在64位系统上占用堆栈上的8个字节.
应该注意的是,C没有堆栈或堆的概念,尽管前面的答案是正确的~99%的时间并且给出了很好的洞察力.
C为对象定义了三个存储持续时间:静态,自动和已分配.(§6.2.4.1)
静态对象(例如全局变量)在整个程序的持续时间内可用.
只要变量在范围内,就会存在自动对象.一旦超出范围,它们就不复存在了.
请注意,这是两个极端.C为您提供了一个点:分配的对象.(搜索项将是动态分配的内存.)有了这些,您可以告诉计算机何时应该开始和结束它们的存在.这是通过使用标准函数malloc()(或衍生物)和free()来完成的.
严格地说,你没有要调用的free() .或者你可以这样做(你必须阅读关于这个权威点的标准),但你可以在main()结束时,在程序终止之前完成所有操作.或者,让它留给操作系统为你做(大多数,如果不是全部的话).但是这又是一个极端 - 当你调用malloc()时,对象就会出现,当你的程序终止时就会出去.
我不应该在这里详细谈论实际意义:记忆是有限的.在内存不足之前,您只能分配这么多字节.对所有东西使用静态对象会太浪费; 尝试重用块或一大块静态内存将是困难的,并且在任何情况下都类似于动态分配方法.对长寿命对象使用自动存储将迫使您使其范围尽可能大,无论如何大致对应于静态对象的范围.
-
现在,一些说明:
{ int *temp = malloc(sizeof(int)); *temp = 5; //free(temp); }
请注意,temp
这是一个自动对象.只有它的范围才会生存,结束于}.然而,它指向的对象是分配的.它将存在,直到你在其地址上调用free().由于temp
包含该地址的唯一副本,一旦temp
超出范围,您将失去调用free()的机会.一些内存将永久分配,但不可用.这称为内存泄漏.
垃圾收集是管理对象存储的另一种方法.C中的实现可能如下所示:
{ int *temp = gc_malloc(sizeof(int)); *temp = 5; }
在},计算机将决定最后一个引用,temp
分配对象丢失,并释放它是一个好主意.
这是一个权衡,你不必担心free()对象(这不是一个小问题,因为简单的例子可能会让你思考),但这里的gc_malloc()比简单的malloc更复杂( ),并且在那里执行的不可见代码temp
超出了范围.这是一个完全不同的主题,计算机如何决定这temp
是最后的参考.(一些实用的解决方案可能会涉及到围绕"int*temp"编写更多代码.)