Memory management 为什么垃圾收集语言中不允许使用free()?

Memory management 为什么垃圾收集语言中不允许使用free()?,memory-management,garbage-collection,free,Memory Management,Garbage Collection,Free,我在读维基百科上的条目,发现: 无法显式释放托管内存;相反,它是自动垃圾收集的 为什么在具有自动内存管理的语言中,甚至不允许手动管理?我可以看出,在大多数情况下,这是不必要的,但是如果您的内存很紧,并且不想依赖GC来实现智能化,那么它不是很有用吗 我不能说这是答案,但我想到的是,如果你可以释放,你可能会意外地将释放一个指针/引用加倍,或者更糟糕的是,在释放之后再使用一个。这违背了使用c#/java/等语言的要点 当然,一个可能的解决方案是让您的free通过引用获取它的参数,并在释放后将其设置为n

我在读维基百科上的条目,发现:

无法显式释放托管内存;相反,它是自动垃圾收集的


为什么在具有自动内存管理的语言中,甚至不允许手动管理?我可以看出,在大多数情况下,这是不必要的,但是如果您的内存很紧,并且不想依赖GC来实现智能化,那么它不是很有用吗

我不能说这是答案,但我想到的是,如果你可以
释放
,你可能会意外地将
释放
一个指针/引用加倍,或者更糟糕的是,在释放之后再使用一个。这违背了使用c#/java/等语言的要点

当然,一个可能的解决方案是让您的
free
通过引用获取它的参数,并在释放后将其设置为
null
。但是,如果他们传递一个像这样的
r值:
free(whatever())
,该怎么办呢。我想你可能会有一个r值版本的重载,但甚至不知道c是否支持这样的东西:-P


最后,即使这样也不够,因为正如已经指出的,您可以对同一个对象有多个引用。将一个设置为
null
不会阻止其他人访问现在已解除分配的对象。

如果您处于“不希望依赖GC智能化”的情况,那么您很可能错误地为任务选择了框架。在.net中,您可以稍微操纵GC(),在Java中则不确定


我认为你不能免费打电话,因为你开始做GC的一项任务。总的来说,GC的效率可以在某种程度上得到保证,当它以自己认为最好的方式做事时,以及当它做出决定时。如果开发人员干扰GC,可能会降低GC的整体效率。

允许手动管理。例如,在Ruby中,调用
GC.start
将释放所有可以释放的内容,尽管您不能单独释放内容。

有趣的是,您确实可以通过System.GC访问垃圾收集器——尽管从我读到的所有内容来看,强烈建议您允许GC管理自己

有一次,第三方供应商建议我使用以下两行代码来处理带有DLL或COM对象或类似对象的垃圾收集问题:

// Force garbage collection (cleanup event objects from previous run.)
GC.Collect();         // Force an immediate garbage collection of all generations
GC.GetTotalMemory(true);

也就是说,除非我知道引擎盖下到底发生了什么,否则我不会为System.GC操心。在本例中,第三方供应商的建议“修复”了我正在处理的有关其代码的问题。但是我忍不住想知道这是否真的是他们破解代码的一个解决办法…

调用
GC.Collect
几乎总是比使用显式
免费
方法更好。调用
free
仅对无处引用的指针/对象引用有意义。这是一个容易出错的问题,因为您的调用有可能对错误类型的指针进行
free


当运行时环境为您执行引用计数监视时,它知道哪些指针可以安全释放,哪些不安全,因此让GC决定可以释放哪些内存可以避免出现一类难看的错误。您可以考虑同时使用
GC
free
的运行时实现,其中显式调用单个内存块的
free
可能比运行完整的
GC.Collect
快得多(但不要期望“手动”释放所有可能的内存块都比GC快)。但是我认为C#、CLI(以及其他带有垃圾收集器的语言,如Java)的设计者们已经决定在这里更注重健壮性和安全性,而不是速度。

具有自动内存管理的语言旨在提供大量的内存安全保证,这是任何手动内存管理都无法提供的

预防的问题包括

  • 双重
    free()
    s
  • 对指向您不拥有的内存的指针调用
    free()
    ,会导致在其他地方非法访问
  • 在一个不是分配函数返回值的指针上调用< <代码>(或代码>),例如在堆栈或数组中间或其他分配中获取某个对象的地址。
  • 取消对已被
    释放()的内存的指针的引用

此外,当GC将活动对象移动到整合区域时,自动管理可以提高性能。这提高了引用的局部性,从而提高了缓存性能。

垃圾收集通过确保内存分配不会出现别名来强制执行内存分配器的类型安全。也就是说,如果一段内存当前被视为类型
T
,那么内存分配器可以保证(通过垃圾收集)当该引用处于活动状态时,它将始终引用
T
。更具体地说,这意味着内存分配器永远不会以不同类型返回该内存

现在,如果内存分配器允许手动
free()
并使用垃圾收集,那么它必须确保您
free()
'd的内存不被其他任何人引用;换句话说,传入到
free()
的引用是对该内存的唯一引用。在大多数情况下,如果任意调用
free()
,执行此操作的成本非常高,因此大多数使用垃圾收集的内存分配器都不允许这样做


这并不是说这是不可能的;如果可以表示单个引用类型,则可以手动管理它。但是在这一点上,停止使用GC语言或者干脆不用担心它会更容易。

许多其他答案都很好地解释了GC是如何工作的,以及在针对提供GC的运行时系统编程时应该如何思考

我想增加一个技巧t