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

时间:2010-03-25 10:28:45

标签: c# .net destructor

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

还有一些可能是愚蠢的问题:

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

3 个答案:

答案 0 :(得分:22)

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

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

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

答案 1 :(得分:4)

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

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

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

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

答案 2 :(得分:3)

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