析构函数 – 如果应用程序崩溃,它会被调用吗?

如果应用程序崩溃,是否会调用析构函数? 如果它是一个未处理的exception,我猜它确实如此,但更严重的错误,或者用户杀死应用程序进程之类的东西呢?

还有一些潜在的愚蠢问题:

  • 当应用程序退出并且所有终结器都已执行时,应用程序中的所有对象会发生什么 – 对象是否被垃圾收集,或者它们是否以某种方式全部“卸载”了进程或应用程序域?
  • 是每个应用程序的垃圾收集器部分(在同一个进程中运行)还是独立的?

我鼓励你自己尝试一下。 例如:

using System; class Program { static void Main(string[] args) { var t = new Test(); throw new Exception("kaboom"); } } class Test { ~Test() { Console.WriteLine("finalizer called"); } } 

在命令提示符下运行此命令,以便您可以看到最后一次喘息。 首先将throw语句注释掉。

与Windows中任何未处理的exception一样,Windows提供的默认exceptionfilter调用WerFault.exe显示的Windows错误报告对话框。 如果单击“关闭程序”,WerFault将使用TerminateProcess()来终止该程序。 这是一个快速结束,没有机会运行终结器线程,就像程序正常退出时一样。

Windows然后负责清理弹片。 它会自动关闭程序可能已打开的任何操作系统句柄,但没有机会在终结器中关闭。 文件是这里比较棘手的问题,它们的缓冲区不会被刷新,你很容易在磁盘上找到部分写入的文件。

我甚至不知道C#,但根据我对其他编程语言的经验,我猜:如果一个应用程序崩溃,那就意味着它有严重错误。 不正确的内存处理等。在这种情况下,任何编程语言尝试执行析构函数/解除分配器/终结器/ …都会很奇怪。 事情可能会更加错误;)

更新:(忘了尝试回答你的其他问题),而不是C#特定的,但通常无法保证destructors / deallocators / finalizers / …实际上被调用。 其原因在于,当一个进程退出时,简单地“删除”用于该进程的内存块比运行其析构函数等来清理内存更容易和更有效。

我不知道如何在不涉及太多技术细节的情况下回答你的上一个问题。 有几种方法可以设计垃圾收集器并使其运行,最简单的方法是垃圾收集停止当前进程并在完成后继续进行,尽管也可能(但更难)使垃圾收集器同时运行与他们正在收集的内存的进程。

您可能想要阅读垃圾收集理论以更好地理解所有这些。 实际上有一个关于这个主题的整个网站: http://www.memorymanagement.org

如果杀死一个应用程序,应用程序将几乎100%立即失去控制,并且它没有机会调用析构函数。