混合模式C ++ / CLI应用程序无法正常关闭CLR无法正常、应用程序、模式、CLR

2023-09-03 07:07:08 作者:有一天我要洋人翻译文言文

我的混合模式的MFC应用程序正在创建假内存泄漏,因为CRT没有足够的时间来关闭前的MFC DLL关闭。

我有一个非常简单的小应用程序,显示问题:

的#include< WINDOWS.H> #包括<的iostream> 结构LongTimeToDestroy {   〜LongTimeToDestroy()   {     性病::法院<< 将调用! <<的std :: ENDL;     睡眠(3000);     性病::法院<< 不会被调用! <<的std :: ENDL;   } }; LongTimeToDestroy gJamsUpTheCRT; 诠释的main() { }

编译与的cl.exe / CLR TEST.CPP 。在运行时,您可以:

 将调用!
 

问题的关键是:在 gJamsUpTheCRT 中声明的任何静态/全局变量将不会被释放。例如,在我的情况下MFC CWinApp派生类是没有清理。

这是预期的行为?我想,让我的应用程序完全关闭。

谢谢

解决方案   

这是预期的行为?

是的,但你必须阅读在CLI规范小字。它承诺,对管理对象的终结程序终止时被调用。但与终结器线程,这是否得到两秒钟的警告,以完成这项工作。如果需要更长的时间,然后在CLR假定有一些完全错误的。就像一个同步对象,是不会得到信号code阻塞的常见的诅咒。它与处理通过的终止执行的终结线程,并允许该程序终止。没有诊断。

PS图层混合模式没有减去

您将必须解决这个限制。

My mixed-mode MFC application is creating false memory leaks because the CRT doesn't have time to shut down before the MFC dll is shut down.

I have a very simple little app that shows the problem:

#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()
{
}

Compile with cl.exe /clr test.cpp. When run, you get:

Will get called!

The crux of the problem is: any static/global variables that were declared before gJamsUpTheCRT will not be deallocated. For example, in my case the MFC CWinApp-derived class is not cleaned up.

Is this expected behaviour? I would like to allow my app to completely shut down.

Thanks,

解决方案

Is this expected behaviour?

Yes, although you have to read the fine print in the CLI spec. Which promises that finalizers on managed objects are called when the program terminates. But with the caveat that the finalizer thread that does this gets two seconds to get the job done. If it takes longer then the CLR assumes that there's something drastically wrong. Like the common curse of having code blocking on a synchronization object that isn't going to get signaled. Which it deals with by aborting the finalizer thread and allowing the program to terminate. No diagnostic.

You'll have to work around this restriction.