gpt4 book ai didi

C#语言 : Garbage Collection, SuppressFinalize

转载 作者:可可西里 更新时间:2023-11-01 03:03:52 26 4
gpt4 key购买 nike

我正在阅读“The C# Language”,第 4 版,它讨论垃圾收集如下:

"BILL WAGNER: The following rule is an important difference between C# and other managed environments.

Prior to an application’s termination, destructor's for all of its objects that have not yet been garbage collected are called, unless such cleanup has been suppressed (by a call to the library method GC.SuppressFinalize, for example)."

所以我有几个问题:

  • 问题 1。为什么 .net 在这里不同于其他托管环境(我想这是在暗示 Java?)?有什么特别的设计问题吗?

  • 问题 2。调用 GC.SuppressFinalize 的对象会发生什么情况?我知道这意味着 GC 不会调用此类对象的终结器(析构函数),如果是这样,这些对象何时会真正被销毁,以便分配的内存位返回到堆中?不然会内存泄漏吗?

最佳答案

What will happened to objects that GC.SuppressFinalize is called? I understand that this means GC will not call such objects' finalizer (destructor), if so, when will these objects got really destructed? otherwise there'll be Memory Leak right?

你对finalization的用途有误解。终结是为了清理不是托管内存的资源。

假设您有一个包含整数字段的引用类型对象。该整数字段恰好是通过调用非托管代码打开文件而获得的文件句柄。

由于某些其他程序可能想要访问该文件,因此尽快关闭该文件是礼貌的做法。但是 .NET 运行时不知道这个整数对操作系统有什么特殊意义。它只是一个整数。

解决此问题的方法通常是将对象标记为实现 IDisposable,然后在完成处理后立即对该对象调用“Dispose”。然后您执行“Dispose”关闭文件。

请注意,这里没有什么特别的事情发生。清理非托管资源的方法称为“Dispose”,需要处置的对象实现 IDisposable 只是一种约定。垃圾回收对此一无所知。

那么现在问题来了:如果有人忘记调用 Dispose 怎么办?文件是否永远保持打开状态? (明明进程结束时文件会被关闭,但是进程运行时间长了怎么办?)

要解决这个问题,您可以使用终结器。它是如何工作的?

当一个对象即将被垃圾回收时,垃圾回收器会检查它是否有终结器。如果是这样,那么它不会对它进行垃圾回收,而是将它放在终结器队列中。在未来某个未指定的时间点,运行一个线程来检查队列并在每个对象上调用一个特殊的“Finalize”方法。之后,对象从终结队列中移除并标记为“嘿,我已经被终结了”。该对象现在再次符合收集条件,因此垃圾收集器最终会运行并收集该对象, 不会将其放入终结队列。

很明显,“Finalize”和“Dispose”经常需要做同样的事情。

但是现在另一个问题出现了。假设您处理一个对象。 现在不需要定稿了。 定稿很昂贵;它使死对象存活的时间比需要的时间长得多。因此,传统上处理一个对象时,Dispose 的实现不仅会关闭非托管资源,还会将该对象标记为“该对象已经被终结,不要再次终结”。这样它就可以诱使垃圾收集器不将对象放入终结队列。

那么让我们回答您的具体问题:

What will happened to objects that GC.SuppressFinalize is called?

当对象死亡时,垃圾收集器将简单地回收对象的内存,而不会将对象放入终结器队列。

I understand that this means GC will not call such objects' finalizer

GC 从不 调用终结器。终结器线程是唯一调用终结器的线程。

when will these objects got really destructed?

不清楚您所说的“破坏”是什么意思。如果您的意思是“终结器何时运行?”答案是“从不”,因为你说过要抑制最终确定。如果你的意思是“什么时候回收托管堆中的内存?”,答案是“一旦对象被垃圾收集器识别为死亡”。这将比正常情况更快发生,因为终结器队列不会使对象保持事件状态。

关于C#语言 : Garbage Collection, SuppressFinalize,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6652044/

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