在程序中,如果声明了变量,它会分配空间,并且在程序结束时,在动态内存分配的情况下释放空间。我知道它在堆中分配空间,但我的问题是:为什么编译器会在堆中隐式释放内存?
答案 0 :(得分:4)
为什么编译器无法在堆中隐式释放内存
因为它不知道/无法判断是否还有其他东西需要访问堆节点。
您在这里谈论的是垃圾收集。 C的类型系统不足以实现(非保守)垃圾收集。
请注意,即使在垃圾收集语言中,编译器也很少决定是否/何时解除分配动态分配的堆节点。
答案 1 :(得分:1)
您正在谈论动态内存分配,这意味着使用malloc()
和朋友创建对象。在这种情况下,许多实现使用类似" 堆"操作系统提供。这样的操作系统通常在退出时执行必要的清理。
但要注意 C对此并不了解。 C只指定了一个称为已分配对象且具有动态存储持续时间的东西,这意味着它保持活动直到您调用free()
。由于C的设计方式几乎可以在任何地方实现,因此它甚至不需要操作系统。因此,虽然省略free()
适用于您的典型PC等,但此代码可能会在某些平台上出现问题,而这些平台上没有任何内容可以在您之后清理#34;。您甚至可以在长时间运行的程序中遇到问题,因为当您从未调用free()
时,分配的对象可能累积到不断增长的数量,这会导致内存泄漏
也就是说,C 包含隐式释放的简单概念:具有自动存储持续时间的对象。一旦执行离开其封闭范围,它们就会被释放。您在函数内声明的任何变量默认情况下都是自动存储持续时间。
另请注意,许多较新的语言并不要求您为动态分配的对象显式管理内存。这只能起作用,因为它们带有一些运行时代码,其中包含垃圾收集器。因此,用这些语言编写的程序需要额外的代码,例如链接到它(或者是执行代码的虚拟机的一部分,例如Java中的情况)。 C不包含这样的东西,但有可用于C的垃圾收集器,您可以使用显式。如果您对此感兴趣,可以查看Boehm GC。
答案 2 :(得分:0)
这意味着编译器必须改变程序的语义,这在编译器首先应该做的事情之外。
出于性能或其他原因,有几种可以想象的情况下您不希望释放堆内存。
垃圾收集,正如他们的答案所指,它依赖于运行时系统跟踪你的内存区域及其引用,但C中不存在这样的运行时。
答案 3 :(得分:0)
编译器无法做到这一点,因为它是运行时决策。如果不执行程序,您无法知道何时解除分配。
这是在垃圾收集系统中完成的。
这段代码怎么样:
int* p[1000000];
for (i= 0; i < 1000000; i++)
{
p[i]= malloc(1000000);
// Initialize this block
}
for (i= 0; i < 1000000; i++)
{
if (Condition(i))
{
// Process this block
}
}
答案 4 :(得分:0)
编译器只是将您的C代码转换为机器代码。它不“知道”在程序代码中访问分配的内存块多长时间,因为它不运行代码。为了允许自动释放,需要一个特殊的运行时工具来跟踪对堆上对象的引用 - 比如C#和JavaScript等语言中使用的垃圾收集器。但是,这些垃圾收集器通常不会立即释放内存,而是等到内存不足。然后他们将处理他们迄今为止检测到的所有未使用的“垃圾”内存。