【问题标题】:Garbage Collector no more references垃圾收集器不再参考
【发布时间】:2014-04-21 07:23:17
【问题描述】:

我一直在阅读有关 C# 中 GC 的内容,并且我发现一些真实的陈述非常有趣。

假设我有以下方法:

public void Foo()
{
   Animal eAnimal = new Animal();
   eAnimal.Name = "Matthew";

   GC.Collect();

   ...more code not using eAnimal...

   return;
}

假设在GC.Collect()语句中,GC发现new Animal()对象对应的内存地址在代码中不再被引用因此适合处置。

据我所知,即使在 GC.Collect() 语句中,堆栈中也有对 new Animal() 的引用(甚至可能存储在一些 CPU 注册表)。我知道如果我检查代码虽然该值存在于堆栈中,但在代码的逻辑中不再使用,但我想这种分析可以在编译时完成,而不是在运行时完成。

GC 怎么知道即使堆栈中有对堆的引用,该引用也不会在程序的未来语句中以任何方式使用?

我最好的猜测是编译会考虑到这一点,并创建适当的指令来清理堆栈中的引用,然后使 GC 工作更容易。但这似乎给生成的代码增加了很多开销。

编辑:我正在读一本关于考试 70-483 的书,上面写着:

StreamWriter stream = File.CreateText(“temp.dat”);
stream.Write(“some data”);
GC.Collect()

在 Release 模式下运行这段代码时,垃圾收集器会看到 不再引用流,它将释放与流相关的任何内存- 编写器实例。

【问题讨论】:

  • 但是您描述的方式是唯一可行的方式。这有什么好惊讶的?在函数返回之前,所有这些引用都需要在某个时候“释放”。为什么不在打电话给GC.Collect() 之前做呢?
  • Supposedly in the GC.Collect() statement, the GC figures out that the memory address corresponding the the new Animal() object is not longer referenced in the code and thus is appropriate to dispose. 根据谁?
  • @Kyle,我编辑了我的问题。
  • @JonathonReinhart,好吧,不要假设 Collect() 和 return 之间没有代码。我会在我的问题中解决这个问题。

标签: c# .net garbage-collection clr


【解决方案1】:

您没有从您的方法返回对该对象的引用,因此当您调用GC.Collect() 时,它会查看该对象的使用位置,并在集合调用之后发现没有其他任何东西会引用它。正如您所指出的,调用后的代码都没有使用该对象,因此 GC 将安全地处理它。

MSDN Example 很好地解释了与您所拥有的情况类似的情况。

垃圾回收操作综合讲解:http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

【讨论】:

  • 在 MSDN 示例中,被调用方法的堆栈已经死亡,因此当调用 Collect() 时,这些引用不存在。在我的示例中,当前堆栈仍然存在,因此情况不同。我的问题是它如何知道调用后的代码不使用该对象。
  • @MatthewAzkimov 从某种意义上说,您在收集电话后没有使用您的代码。为什么 GC 不会删除不再以任何方式引用的对象?这对你来说是一本好书:msdn.microsoft.com/en-us/magazine/bb985010.aspx
  • 我并不是说不应该。我在问如果(我猜)的堆栈中仍然存在对 Animal 对象堆中的内存地址的内存引用,它怎么知道不再被引用。
  • @MatthewAzkimov 查看我的更新答案中的链接。这是对垃圾收集器如何工作的非常透彻的解释。远远超过可以在这里发布。
  • 他们的解释是“活动根列表由即时 (JIT) 编译器和公共语言运行时维护,并且可供垃圾收集器的算法访问。”。我想我得问问微软真的“如何”......
猜你喜欢
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 2011-11-07
  • 2013-04-01
  • 2012-06-23
相关资源
最近更新 更多