Mixed-mode C++/CLI app not shutting down CLR correctly
Asked Answered
S

2

1

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,

Shorthorn answered 19/4, 2012 at 0:15 Comment(0)
C
3

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.

Crossstaff answered 19/4, 2012 at 0:31 Comment(2)
The Joe Duffy link supplied in the link Porges gave says that "Although configurable, by default the CLR will let finalizers run for 2 seconds". Do you know how to configure this?Shorthorn
No. Other than by hosting the CLR yourself, maybe. Realistically, when your finalizer has already burned 5 billion cpu cycles and didn't get the job done then adding some more isn't very likely to bring relief.Crossstaff
P
1

I believe this answers your problem.

The relevant text:

Although configurable, by default the CLR will let finalizers run for 2 seconds before becoming impatient; if this timeout is exceeded, the finalizer thread is stopped, and shutdown continues without draining the rest of the finalizer queue.

So you really shouldn't have any destructors performing tasks that will take time.

Edit: actually, that isn't a CLR class, so it shouldn't be on the finalization queue? This might be misleading.

Path answered 19/4, 2012 at 0:26 Comment(2)
this seems extreme - how can this be configured? Im guessing that my scenario (MFC statically linking against C++/CLI lib) is not usual - would this be corrected if I put all the C++/CLI stuff into an MFC dll and linked against that, instead?Shorthorn
Just a further note to your edit: it seems that the CRT cleanup is handled by the main modules '.cctor', which I suppose places this cleanup somewhere inside its 'finalizer queue'.Shorthorn

© 2022 - 2024 — McMap. All rights reserved.