析构函数不能保证被调用。

10

我看到了以下引用:“析构函数不能保证被调用。” 这让我有点害怕。

它还指出,即使是 try finally 块也可能会被中断,从而导致内存泄漏。 它提供了一种解决方案,即将代码放置在 CER (受限执行区域) 中或从 CriticalFinalizerObject 派生。

我的问题是

  1. 使用 CriticalFinalizerObject 有什么权衡之处(如果有的话)?
  2. 是否存在从 CriticalFinalizerObject 派生非常有用的情况?
  3. 只有当我开始遇到内存泄漏时才应该担心使用它吗?

10
我认为你根本不需要担心这个。 - David Heffernan
2
请问您能给我们提供源链接吗? - Leonard Brünings
2
@Jalal - “finally代码块始终会被执行”可不是这样的,如果我拔掉插头或杀掉进程,它就不会执行了。 - Marc Gravell
3
如果你拔掉插头,就不必担心泄漏了,这是最好的清理方式 ;) - Leonard Brünings
1
@KiNGPiN,它来自于《微软编程Visual C# 2008:语言》。 - Jethro
显示剩余13条评论
4个回答

3

我知道IDisposable类是做什么的以及如何使用它,但正如我上面的帖子所述,这可能会导致内存泄漏。 - Jethro
好的。但是这些情况应该明确处理,例如在另一篇帖子中提到的使用Try{}finally{}块。就像Raymong Chen所说:
一个正确编写的程序不能假设finalizers将永远运行。<<
- Boas Enkler
我会将您最后一个链接重命名为“如何不清理非托管资源”。非托管资源是唯一应该使用关键终结的东西。 - CodesInChaos
我相信 "析构函数不能保证被调用" 的警告是由于一些晦涩的边缘情况而存在的。 - IAbstract

1
关于问题#3:内存泄漏通常是由以下原因引起的:
  • 未释放非托管资源。对于这些资源,使用IDisposable(在终结器中回退调用Dispose())是最好的方法。

  • 对托管对象的引用被维护,因为其他对象仍然指向它们,即使它们应该被删除。我认为这更多是代码质量的问题,而不是垃圾收集的低级问题。

除非你真正遇到内存泄漏,否则你不应该担心它,并且不要试图强制任何行为。


那似乎是我从人们那里得到的普遍答案。感谢您的回答。 - Jethro

0
我建议对于所有需要销毁的资源均使用IDisposable接口,并在using块中使用它们。

2
那么,using块在技术上与try-finally有什么不同?(是的,这个问题是修辞性的。) - Heinzi
2
这并没有什么帮助。using 只是 try/finally 的语法糖。 - David Heffernan

0
通常情况下,普通终结器和关键终结器之间的区别只有在 AppDomain 卸载时才变得重要。由于大多数非托管资源会在进程卸载时自动消失,因此您通常只需要担心关键终结化,如果您想在保持进程运行的同时干净地卸载 AppDomain。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接