我正在阅读“C#语言”,第4版,它谈到垃圾收集如下:
"BILL :以下规则是C#与其他托管环境之间的一个重要区别。
在应用程序终止之前,将调用尚未被垃圾回收的所有对象的析构函数,除非这种清理已被抑制(例如,通过调用库方法GC.SuppressFinalize )。
我有几个问题要问:
GC.SuppressFinalize的对象会发生什么变化?据我所知,这意味着GC不会调用这些对象的终结器(析构函数),如果是,这些对象什么时候才会真正销毁,从而将分配的内存位返回到堆中?否则会有内存泄漏?发布于 2011-07-11 15:11:59
,GC.SuppressFinalize被调用的对象会发生什么变化?我知道这意味着GC不会调用这些对象的终结器(析构函数),如果是,这些对象什么时候才会真正被破坏?否则会有内存泄漏,对吧?
你对终结的目的有一个误解。终结是用于清理非托管内存的资源。
假设您有一个包含整数字段的引用类型的对象。这个整数字段恰好是一个文件的句柄,该句柄是通过调用非托管代码来打开该文件获得的。
由于其他程序可能希望访问该文件,因此尽快关闭该文件是礼貌的。但是.NET运行时不知道这个整数对操作系统有什么特殊意义。只是个整数。
解决此问题的方法通常是将对象标记为实现IDisposable,然后在处理完该对象后立即对其调用"Dispose“。您的"Dispose“实现将关闭该文件。
请注意,这里没有什么特别的事情。一个清理非托管资源的方法称为"Dispose“,需要释放的对象实现IDisposable,这只是一种惯例。垃圾收集部门对此一无所知。
所以现在问题出现了:如果有人忘了叫处分怎么办?文件会永远打开吗?(显然,当进程结束时,文件将被关闭,但如果进程运行很长时间,怎么办?)
要解决这个问题,您可以使用终结器。这是如何工作的呢?
当一个对象即将被垃圾收集时,垃圾收集器会检查它是否有终结器。如果是这样的话,那么它将把它放到终结器队列中,而不是垃圾收集。在将来的某个未指定的点,线程会运行一个线程来检查队列,并对每个对象调用一个特殊的"Finalize“方法。之后,对象将从终结队列中移除,并标记为“嗨,我已经完成了”。现在,该对象再次可用于收集,因此垃圾收集器最终运行并收集对象,而不将其放到终结队列中。
显然,“终结”和“处置”经常需要做同样的事情。
但现在出现了另一个问题。假设您处理了一个对象。现在不需要最后定稿了。终结是昂贵的;它使一个死对象存活的时间比它需要的时间长得多。因此,传统上,当处理对象时,Dispose的实现不仅关闭非托管资源,还将对象标记为“该对象已经完成,不要再次完成”。这样,垃圾收集器就不会将对象放到终结队列中。
所以让我们回答你的具体问题:
,GC.SuppressFinalize被调用的对象会发生什么变化?
当对象死后,垃圾收集器将简单地回收对象的内存,而不会将对象放到终结器队列中。
我知道这意味着GC不会调用这些对象的终结器
GC从不调用终结器。终结器线程是唯一调用终结器的东西。
,这些对象什么时候才会真正被摧毁?
你所说的“毁灭”是什么意思还不清楚。如果你的意思是“终结器什么时候运行?”答案是“永远不会”,因为你说要压制终结。如果您的意思是“什么时候才能回收托管堆中的内存?”,答案是“当垃圾回收器将对象标识为死的时候”。这将比正常情况下更早地发生,因为终结器队列将不会使对象处于活动状态。
发布于 2011-07-11 15:01:59
Q1:我怀疑这是因为它更关心实现出色的性能,而不是为简单性做出了相当大的牺牲。
Q2:由于一开始甚至不能保证调用终结器(即使SuppressFinalize不存在),所以只有在您已经释放了资源之后,才应该使用终结器。否则,您应该使用IDisposable来释放资源。
最后审定!=销毁
析构函数(在C++意义上)并不存在于.NET中--因为在某种意义上,每个对象都有一个称为垃圾收集器的“析构函数”。:)
C#所说的“析构函数”实际上是终结器。终结器用于处理对象分配的内存以外的其他内容,如文件句柄等。因此,并非每个对象都有终结器。内存总是由GC释放的,这样就不会有内存泄漏。
发布于 2011-07-11 14:55:40
我只知道第二个答案:SuppressFinalize is called when the object has already been destructed, i.e., by IDisposable.Dispose.,所以它不应该再被破坏。
这是因为终结器是在非确定时间发生的资源清理。添加IDisposable是为了允许在特定、可预测的时间进行资源清理。
编辑:在进程终止时,内存泄漏是不重要的。当进程终止时,它的堆由Windows收集,所以一个对象的内存是否返回到堆并不重要。
https://stackoverflow.com/questions/6652044
复制相似问题