垃圾收集和范围界定在C#中是如何工作的?

2024-06-16 14:20:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在学习C#coming from python,我想知道C#垃圾收集器是如何工作的——我发现,一旦我知道python在幕后做了什么,我就对它有了更多的了解,并且希望避免犯我在学习python时最初犯的那种noob错误。

我找不到任何很好的解释,当一个项目被垃圾收集时,留下了一些问题,比如

  1. “当对象的最后一个引用超出作用域时,该对象会发生什么情况?”该对象是否被垃圾回收,或者当您返回到定义它的作用域时它是否仍然存在?
  2. “在什么情况下引用的数量会减少?”让我想知道它是否使用了引用计数或其他技术。。。

回答这些问题,或者更清楚地了解实际情况将赢得cookies(或upvots),如果您的回答将其与python的做事方式相比较,则会更好。我对哪个更好不感兴趣,只关心细节。另外,我在programmers.stackexchange上的原帖上的答案将非常感谢。。。


Tags: 项目对象from数量定义错误情况作用域
3条回答

垃圾回收不会由超出范围的引用触发。垃圾收集通常在为新对象分配存储空间时触发,特别是当第0代的预算用完时。一、 e.在对象符合垃圾收集条件和实际收集对象之间可能存在明显的延迟。正如其他人已经指出的,CLR不使用引用计数。相反,它采用了标记和扫描方法。

Jeffrey Ricther的书CLR via C#是关于垃圾收集工作的所有细节的一个很好的信息来源。这本书详细介绍了堆是如何分区的以及垃圾收集是如何工作的。如果您对.NET实现细节感兴趣,强烈建议您使用。

在对象的最后一个引用消失后的某个不确定时间点,将收集该对象。

第一个问题的第二部分没有意义。
如果可以回到定义对象的范围(例如lambda表达式),显然仍然有一个引用。

GC根本不使用引用计数。
相反,它使用mark-and-sweep algorithm

dotnet GC引擎是一个标记和扫描引擎,而不是像python中使用的那样的引用计数器引擎。系统不维护对变量的引用计数,而是在需要回收RAM时运行“集合”,标记所有当前可访问的指针,并删除所有无法访问的指针(因此超出范围)。

您可以在这里了解它的工作原理:
http://msdn.microsoft.com/en-us/library/ee787088.aspx

系统通过从特定的“根”位置(如全局对象和堆栈上的对象)开始查找“可访问”对象,并跟踪这些对象引用的所有对象以及这些对象引用的所有对象等,直到构建一个完整的树。这比听起来要快。

相关问题 更多 >