Eric Lippert引用(Safe in C# not in C++, simple return of pointer / reference,答案3)。
另外,请注意,它不是对Person对象的任何引用使其保持活动状态。参考必须扎根。你可以有两个Person对象相互引用但是无法访问;每个人都有参考的事实并不能让他们活着;其中一个参考文献必须扎根。
我不明白,有人可以解释一下有根参考吗?
答案 0 :(得分:34)
这意味着GC根。
请仔细阅读this article,也许这有助于您理解:
GC根本身不是对象,而是对象的引用。 GC根引用的任何对象将自动在下一个垃圾回收中存活。 .NET中有四种主要的root用户:
当前正在运行的方法中的局部变量被视为GC根。这些变量引用的对象始终可以通过声明它们的方法立即访问,因此必须保留它们。这些根的生命周期可能取决于程序的构建方式。在调试版本中,只要方法在堆栈上,局部变量就会持续。在发布版本中,JIT能够查看程序结构,以计算出该方法可以使用变量的执行中的最后一点,并在不再需要时将其丢弃。此策略并不总是使用,可以关闭,例如,通过在调试器中运行程序。
静态变量也始终被视为GC根。它们引用的对象可以由声明它们的类(或程序的其余部分,如果它们是公共的)随时访问,因此.NET将始终保留它们。声明为'thread static'的变量只会持续该线程正在运行的时间。
如果托管对象通过互操作传递给非托管COM +库,那么它也将成为具有引用计数的GC根。这是因为COM +不进行垃圾收集:它使用引用计数系统;一旦COM +库通过将引用计数设置为0来完成对象,它就不再是GC根,可以再次收集。
如果一个对象有一个终结器,当垃圾收集器决定它不再“活动”时,它不会被立即删除。相反,它在.NET调用终结器方法之前成为一种特殊的根。这意味着这些对象通常需要从内存中删除多个垃圾收集,因为它们将在第一次被发现未使用时存活。
(强调我的)
答案 1 :(得分:11)
有各种根对象,比如CLR内部对象,元数据对象等。post may help:
变量和GC根
- 值类型的变量直接表示堆栈上的值类型实例的地址
- Value Type实例的引用变量称为Managed Pointer,是指向堆栈上Value Type实例的起始地址的指针
- 引用类型的变量(UDT,数组,字符串,代理和接口类型变量)是指向在GC堆上创建的引用类型实例的指针
- CPU寄存器可以包含托管指针或对象引用
- AppDomain wide Handle表包含GC句柄,这些句柄是指向内存中固定引用类型实例的指针。这些Handle表还包含静态Value Type实例的Managed Pointers(或Object References?)和静态Reference Type实例的Object References
- 线程本地存储(TLS)可以包含对象引用
- FReachable Queue包含引用类型的对象引用,这些引用类型未被任何上述变量类型引用,并且finalize方法调用正在等待
CLR的垃圾收集器使用上述变量(也称为GC根)在垃圾收集阶段跟踪对象引用。位于GC堆中的任何引用类型实例(在上述任何变量类型中都没有对象引用(FReachable Queue除外))被视为垃圾收集的候选者,并从GC堆中删除。如果要删除的引用类型实例实现了Finalize方法,则将对象引用放在FReachable Queue上,以便通过单独的Finalizer线程调用Finalize方法。一旦Finalizer线程在Object Reference上完成Finalize方法调用,就会从GC堆中删除相应的Reference Type实例。