Деструктор - вызывается ли он, если приложение вылетает - PullRequest
16 голосов
/ 25 марта 2010

Деструктор вызывается в случае сбоя приложения? Если это необработанное исключение, я предполагаю, что это так, но как насчет более серьезных ошибок или чего-то вроде того, как пользователь убивает процесс приложения?

И еще несколько потенциально глупых вопросов:

  • что происходит со всеми объектами в приложении, когда приложение завершается и все финализаторы выполняются - объекты собирают мусор или все они каким-то образом «выгружаются» из процесса или домена приложения?
  • является ли сборщик мусора частью каждого приложения (выполняется в одном и том же процессе) или он независим?

Ответы [ 3 ]

22 голосов
/ 25 марта 2010

Я бы посоветовал вам попробовать это для себя. Например:

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, вызывает диалоговое окно отчетов об ошибках Windows, отображаемое WerFault.exe. Если вы нажмете «Закрыть программу», WerFault будет использовать TerminateProcess (), чтобы убить программу. Это быстрый конец, нет возможности запустить поток финализатора, как это происходит при нормальном выходе из программы.

Windows заботится о том, чтобы очистить шрапнель. Он автоматически закрывает все дескрипторы операционной системы, которые ваша программа могла открыть, но не получила возможности закрыть ее в финализаторе. Здесь проблема с файлами сложнее, их буферы не очищаются, и вы легко получите частично записанный файл на диске.

4 голосов
/ 25 марта 2010

Я даже не знаю C #, но, основываясь на своем опыте работы с другими языками программирования, я могу предположить: если приложение падает, это означает, что с ним что-то серьезно не так. Неправильная обработка памяти и т. Д. Было бы странно для любого языка программирования пытаться выполнить деструкторы / разборки / финализаторы / ... в таком случае. Скорее всего, все пошло бы не так;)

Обновление: (забыл попытаться ответить на другие ваши вопросы) снова, не специфично для C #, но обычно нет никакой гарантии, что деструкторы / освобождающие / финализаторы / ... действительно будут вызваны. Причина этого заключается в том, что при выходе из процесса гораздо проще и эффективнее просто «сжать» блок памяти, используемый для этого процесса, чем запускать деструкторы и т. Д. Для очистки памяти.

Я не уверен, как ответить на ваш последний вопрос, не вдаваясь в технические подробности. Существует несколько способов, с помощью которых сборщики мусора могут быть спроектированы и созданы для работы. Самый простой - сборка мусора останавливает текущий процесс и продолжает его, когда он завершен, хотя также возможно (но более сложно) иметь сборщики мусора, которые работают одновременно. с процессами, память которых они собирают.

Возможно, вы захотите прочитать теорию сборки мусора, чтобы лучше понять все это. На самом деле есть целый сайт только на эту тему: www.memorymanagement.org .

3 голосов
/ 25 марта 2010

Если убить приложение, приложение почти на 100% немедленно потеряло бы управление, и у него нет шансов вызвать деструктор.

...