gpt4 book ai didi

c# - 当 GC 调用 Object.Finalize 时,子对象是否仍然存在?

转载 作者:行者123 更新时间:2023-11-30 22:04:05 24 4
gpt4 key购买 nike

说,我有这个类:

class Test
{
readonly object _child = new Object();

// ...

~Test()
{
// access _child here
// ...
}
}

~Test 被垃圾收集器调用时,_child 对象是否保证仍然存在?或者我应该首先在构造函数中使用 GCHandle.Alloc“固定”_child

最佳答案

作为一个 readonly 字段 _child 你不能失去它的引用(除非你通过反射将它设置为 null)。这意味着在 Test 被垃圾回收之前 _child 肯定会保留在内存中。

此外,您正在使用在垃圾收集之前调用的 Finalizer,只有在下一次通过时,对象的内存才会被回收,此时 _child 将是活。换句话说,当 Finalize 方法被调用时,_child 将存活并且可以安全地访问它。

Finalizer 被调用并不意味着内存将被回收,如果您执行类似下面的操作,Finalize 将被调用但内存不会被回收

class Test
{
readonly object _child = new Object();

private static Test evilInstance;

~Test()
{
evilInstance = this;//Do something crazy
//This resurrects this instance, so memory will not be reclaimed.
}
}

当您处理托管代码时,几乎不需要终结器,它会为垃圾收集器增加额外的工作,并且还会发生我们上面看到的奇怪的事情。

更新:如果您仅将_child 用于lock,则可以安全使用,因为_child 实例不会为空,这意味着它指向一个有效的引用。 Monitor.EnterMonitor.Exit 只关心引用,使用它绝对安全(仅用于锁定)。

What if you need the child's Finalizer to be called only after Test's Finalizer is called?

有一个解决方法:您可以从 SafeHandle 继承 Child 类,这样就可以了。它将确保 TestChild 同时超出范围,它将首先调用 Test 的终结器作为 Child 继承自 SafeHandle,它延迟了它的完成。但是,IMO 不依赖于此。因为与您一起工作的其他程序员可能不知道这一点,这会导致误解。

This critical finalizer also has a weak ordering guarantee, stating that if a normal finalizable object and a critical finalizable object become unreachable at the same time, then the normal object’s finalizer is run first

引自 SafeHandle: A Reliability Case Study

关于c# - 当 GC 调用 Object.Finalize 时,子对象是否仍然存在?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25480569/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com