Приложение С++/CLI смешанного режима не выключает CLR правильно

Мое приложение MFC с смешанным режимом создает ложные утечки памяти, потому что у CRT нет времени для закрытия, прежде чем выключение MFC dll будет закрыто.

У меня очень простое небольшое приложение, которое показывает проблему:

#include <windows.h>
#include <iostream>

struct LongTimeToDestroy
{
  ~LongTimeToDestroy()
  {
    std::cout << "Will get called!" << std::endl;
    Sleep(3000);
    std::cout << "Won't get called!" << std::endl;
  }
};

LongTimeToDestroy gJamsUpTheCRT;

int main()
{
}

Скомпилируйте с помощью cl.exe /clr test.cpp. При запуске вы получаете:

Will get called!

Суть проблемы: любые статические/глобальные переменные, объявленные до gJamsUpTheCRT, не будут освобождены. Например, в моем случае класс MFC CWinApp не очищается.

Является ли это ожидаемым поведением? Я хочу, чтобы приложение полностью отключилось.

Спасибо,

Ответ 1

Является ли это ожидаемым поведением?

Да, хотя вы должны прочитать мелкий шрифт в спецификации CLI. Какой promises, что финализаторы на управляемых объектах вызывается, когда программа завершается. Но с оговоркой, что поток финализатора, который делает это, получает две секунды, чтобы выполнить работу. Если это займет больше времени, CLR предполагает, что там что-то совершенно ошибочное. Подобно общему проклятию блокировки кода на объекте синхронизации, который не собирается сигнализировать. С чем это связано, прервав поток финализатора и разрешив программе завершить работу. Нет диагностики.

Вам придется обойти это ограничение.

Ответ 2

Я верю, что отвечает на вашу проблему.

Соответствующий текст:

Несмотря на то, что конфигурация, по умолчанию, CLR позволяет финализаторам работать в течение 2 секунд, прежде чем стать нетерпеливым; если этот тайм-аут превышен, поток финализатора остановлен, и выключение продолжается, не опуская оставшуюся часть очереди финализатора.

Поэтому у вас действительно не должно быть никаких деструкторов, выполняющих задачи, которые потребуют времени.

Изменить: на самом деле это не CLR-класс, поэтому он не должен находиться в очереди финализации? Это может ввести в заблуждение.