c# - 如果 GC 完成了它的工作,为什么我们会出现内存不足异常?

标签 c# garbage-collection

通常有人告诉我 GC 比我们所有人都聪明,不要惹它,所以我想当内存不足时它会为程序释放内存。那么为什么我有时仍然会在大型对象上出现内存不足异常?

目前我再次接近另一个可能耗尽内存的场景。我有一些类列表的类级字典,它有大约 200,000 个键。 我必须将它保持在全局级别,因此在我的一种方法中的某个地方我需要它,但是一旦我用该方法完成它,我就想释放它的空间。 将其设置为 null 就足够了吗?

private void Foo()
{
   // do stuff with MY_DICTIONARY
   MY_DICTIONARY = null  // ?
   // whew! freeded up memory or not?
}

最佳答案

GC 不确定何时会被调用,确切地说。内存在不再使用的情况下被释放并不是一个直接的问题,它发生在计算机足够开放时可以做到这一点。在许多情况下,这可能会更早而不是更晚,但仍然不能保证它会立即发生。

这就是像 GC.Collect() 这样的方法存在的原因。在大多数情况下,我们不必担心,因为我们正在处理足够小的变量和足够的 RAM,“最终”足以满足我们的使用需求。垃圾收集器是作为实用程序提供的,而不是神。它很有用,因为它几乎适用于所有情况(特别是在应用程序情况下)。在大多数情况下,我们不必担心存储所有那么多数据(如果我们在应用程序中这样做,我们可能需要检查我们的设计以实现一些分页,而不是首先一次显示那么多)。但仅仅因为我们使用托管内存并不能保证它将以可靠的 100% 方式进行管理并且我们可以向它们抛出任何东西。

这就是像 C++ 这样的语言仍然存在的原因之一。正如您所说,GC 非常聪明,并且非常擅长它的工作。因此,不必考虑 mallocfree 并对此抱有一些信任是很好的,但这并不意味着它可以读懂我们的想法。

这有点像巡航控制。您可以在路上行驶并设置巡航控制以保持恒定速度,但是当您开始爬坡时,需要一点时间才能 catch 并开始加大 throttle 以保持速度。同样,它会让你比其他方式更快地从山上掉下来。 GC 知道哪些对象在内存中是可释放的,但它不一定知道上下文的细节,其想法是它在我们的代码后面被动地行动。否则,会导致一些严重的性能问题。

正如许多其他人也指出的那样,我认为从更实际的意义上来说这很重要,GC 当然只会收集不再使用或范围内的资源。因此,如果您的 Dictionary 中的元素在其他地方使用(并且通过引用传递,即是 class),则不会收集它们。此外,如果您将 Dictionary 保留为 static 成员,它将永远不会被收集。

关于c# - 如果 GC 完成了它的工作,为什么我们会出现内存不足异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24943493/

相关文章:

java - Java 垃圾回收是否安全地清除了垃圾数据?

java - 垃圾收集器占用太多 CPU 时间

java - 通过修改对象头掩码字中的位来固定对象

c - 垃圾回收如何与数据段一起工作?

c# - Controller /操作流程为 "three stage operations"?

c# - 使用 linq 将 XML 元素连接到 C# 中的类属性

c# - Windows7 Installer优先使用C#如何在安装过程中将其移回?

c# - IsAssembly/IsFamily 和 IsFamilyOrAssembly 之间的关系

c# - 使用 Binding 时出现 FontImageSource Glyph 问题

node.js - 如何更改 Node.js 内存设置以允许非常大 (>100GB) 内存