什么是“根引用”?

发布于 2024-12-20 19:57:25 字数 365 浏览 0 评论 0原文

引用自 ( 在 C# 中安全,但在C++,简单返回指针/引用, 答案 3),作者:Eric lippert。

另外,请注意,并不是对 Person 对象的任何引用使其保持活动状态。引用必须是 root 的。您可以有两个相互引用但无法访问的 Person 对象;事实上,每个人都有一个参考并不能让他们保持活力;其中一个参考文献必须是 root 的。

我不明白,有人可以解释一下什么是根引用吗?

Quote from ( Safe in C# not in C++, simple return of pointer / reference, answer 3) by Eric lippert.

Also, note that it is not any reference to the Person object that keeps it alive. The reference has to be rooted. You could have two Person objects that reference each other but are otherwise unreachable; the fact that each has a reference does not keep them alive; one of the references has to be rooted.

I dont understand, can someone explain what a rooted reference is?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

渔村楼浪 2024-12-27 19:57:25

这意味着GC根。

阅读这篇文章,也许它会帮助你理解:

GC 根本身并不是对象,而是对对象的引用。 GC 根引用的任何对象将在下一次垃圾回收中自动存活。 .NET 中有四种主要的根:

当前正在运行的方法中的局部变量被视为GC根。这些变量引用的对象始终可以通过声明它们的方法立即访问,因此必须保留它们。这些根的生命周期取决于程序的构建方式。在调试版本中,只要方法在堆栈上,局部变量就会持续存在。在发布版本中,JIT 能够查看程序结构以计算出执行中变量可以被方法使用的最后一点,并在不再需要时将其丢弃。此策略并不总是使用,可以关闭,例如,通过在调试器中运行程序。

静态变量也始终被视为 GC 根。它们引用的对象可以随时由声明它们的类(或者程序的其余部分,如果它们是公共的)访问,因此 .NET 将始终保留它们。声明为“线程静态”的变量只会在该线程运行时持续存在。

如果通过互操作将托管对象传递给非托管 COM+ 库,那么它也将成为具有引用计数的 GC 根。这是因为 COM+ 不进行垃圾收集:相反,它使用引用计数系统;一旦 COM+ 库通过将引用计数设置为 0 来完成对象的处理,它就不再是 GC 根并可以再次被收集。

如果某个对象具有终结器,则当垃圾收集器确定该对象不再“活动”时,该对象不会立即被删除。相反,它会成为一种特殊的根,直到 .NET 调用终结器方法。这意味着这些对象通常需要多次垃圾收集才能从内存中删除,因为它们在第一次被发现未使用时将继续存在。

(强调我的)

It means a GC root.

Have a read through this article, maybe it will help with your understanding:

GC roots are not objects in themselves but are instead references to objects. Any object referenced by a GC root will automatically survive the next garbage collection. There are four main kinds of root in .NET:

A local variable in a method that is currently running is considered to be a GC root. The objects referenced by these variables can always be accessed immediately by the method they are declared in, and so they must be kept around. The lifetime of these roots can depend on the way the program was built. In debug builds, a local variable lasts for as long as the method is on the stack. In release builds, the JIT is able to look at the program structure to work out the last point within the execution that a variable can be used by the method and will discard it when it is no longer required. This strategy isn’t always used and can be turned off, for example, by running the program in a debugger.

Static variables are also always considered GC roots. The objects they reference can be accessed at any time by the class that declared them (or the rest of the program if they are public), so .NET will always keep them around. Variables declared as ‘thread static’ will only last for as long as that thread is running.

If a managed object is passed to an unmanaged COM+ library through interop, then it will also become a GC root with a reference count. This is because COM+ doesn’t do garbage collection: It uses, instead, a reference counting system; once the COM+ library finishes with the object by setting the reference count to 0 it ceases to be a GC root and can be collected again.

If an object has a finalizer, it is not immediately removed when the garbage collector decides it is no longer ‘live’. Instead, it becomes a special kind of root until .NET has called the finalizer method. This means that these objects usually require more than one garbage collection to be removed from memory, as they will survive the first time they are found to be unused.

(emphasis mine)

你对谁都笑 2024-12-27 19:57:25

有各种各样的根对象,例如 CLR 内部对象、元数据对象等。这个 帖子可能有帮助

变量和 GC 根

  • 值类型的变量是堆栈上值类型实例的地址的直接表示
  • 值类型实例的引用变量称为托管指针,是指向堆栈上值类型实例的起始地址的指针
  • 引用类型的变量(UDT、数组、字符串、委托和接口类型变量)是指向 GC 堆上创建的引用类型实例的指针
  • CPU 寄存器可以包含托管指针或对象引用
  • AppDomain 宽句柄表包含 GC 句柄,这些句柄是指向内存中固定引用类型实例的指针。这些句柄表还包含指向静态值类型实例的托管指针(或对象引用?)和指向静态引用类型实例的对象引用
  • 线程本地存储 (TLS) 可以包含对象引用
  • FReachable 队列包含引用类型的对象引用,这些引用类型未被任何上述变量类型引用,并且其 Finalize 方法调用正在等待

CLR 的垃圾收集器使用上述变量(也称为 GC 根)在垃圾收集阶段跟踪对象引用。位于 GC 堆中的任何引用类型实例,如果在上述任何变量类型中都没有对象引用(FReachable 队列除外),则被视为垃圾回收的候选者,并从 GC 堆中删除。如果要删除的引用类型实例实现了 Finalize 方法,则该对象引用将被放入 FReachable 队列中,以便由单独的 Finalizer 线程调用 Finalize 方法。一旦 Finalizer 线程完成对对象引用的 Finalize 方法调用,相应的引用类型实例就会从 GC 堆中删除。

There're all kinds of root objects, like CLR internal objects, metadata objects, etc. This post may help:

Variables and GC Roots

  • A variable of a Value Type is direct representation of the address of the Value Type instance on stack
  • A reference variable to a Value Type instance is called Managed Pointer and is a pointer to the starting address of the Value Type instance on stack
  • A variable of a Reference Type (UDT, Array, String, Delegate and Interface type variables) is a pointer to the Reference Type instance created on GC heap
  • CPU registers can contain Managed Pointers or Object References
  • AppDomain wide Handle tables contain GC handles that are pointers to the pinned Reference Type instances in memory. These Handle tables also contain Managed Pointers (or Object References?) to the static Value Type instances and Object References to the static Reference Type instances
  • Thread Local Storage (TLS) can contain Object References
  • FReachable Queue contains Object References of the Reference Types that are NOT referenced by any of the above variable types and for which finalize method call is pending

CLR's Garbage Collector uses the above variables, also called GC roots, to track down the Object References during garbage collection phase. Any Reference Type instance located in GC heap, for which there is no Object Reference in any of the above variable types (except for the FReachable Queue), is considered a candidate for garbage collection and is removed from GC heap. If the Reference Type instance being removed implements the Finalize method, then the Object Reference is put on FReachable Queue for calling the Finalize method by a separate Finalizer thread. Once the Finalizer thread completes Finalize method call on an Object Reference, the corresponding Reference Type instance is removed from the GC heap.

末蓝 2024-12-27 19:57:25

根是一个存储位置,例如局部变量,它可以包含引用并且已知已被初始化,并且您的程序在将来的某个时刻使用它而无需通过其他对象引用。

Ian GriffithsProgramming C# 10.0中第七章中指出:

根是一个存储位置,例如本地
变量,它可能包含一个引用并且已知已被
已初始化,并且您的程序可以在将来的某个时候使用
无需通过其他对象引用。并非所有存储
位置被认为是根。如果一个对象包含实例字段
对于某些引用类型,该字段不是根,因为在您可以使用之前
它,你需要获取对包含对象的引用,它是
对象本身可能无法访问。然而,引用类型
static 字段是根引用,因为程序可以读取其中的值
该字段随时可用。

另外本文档微软称:

应用程序的根包括静态字段、线程堆栈上的局部变量、CPU 寄存器、GC 句柄和终结队列。每个根要么引用托管堆上的一个对象,要么设置为 null。垃圾收集器可以向运行时的其余部分询问这些根。垃圾收集器使用此列表创建一个图,其中包含从根可访问的所有对象。

根据 Joseph AlbahariC# 12 in a Nutshell,根 根是使对象保持活动状态的东西。如果一个对象没有被根直接或间接引用,那么它将有资格进行垃圾回收。

下图来自同一本书,可以帮助理解:
输入图片此处描述

A root is a storage location, such as local variable, that could contain a reference and is known to have been initialized, and that your program use at some point in the future without needing to go via some other object reference.

In Programming C# 10.0 by Ian Griffiths in the seventh chapter it is stated that:

A root is a storage location, such as a local
variable, that could contain a reference and is known to have been
initialized, and that your program could use at some point in the future
without needing to go via some other object reference. Not all storage
locations are considered to be roots. If an object contains an instance field
of some reference type, that field is not a root, because before you can use
it, you’d need to get hold of a reference to the containing object, and it’s
possible that the object itself is not reachable. However, a reference type
static field is a root reference, because the program can read the value in
that field at any time.

additionally in this document by Microsoft it is said that:

An application's roots include static fields, local variables on a thread's stack, CPU registers, GC handles, and the finalize queue. Each root either refers to an object on the managed heap or is set to null. The garbage collector can ask the rest of the runtime for these roots. The garbage collector uses this list to create a graph that contains all the objects that are reachable from the roots.

According to C# 12 in a Nutshell by Joseph Albahari, Root A root is something that keeps an object alive. If an object is not directly or indirectly referenced by a root, it will be eligible for garbage collection.

The figure below from the same book can help in understanding:
enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文