Exception on exit() when using C# event source with c++ sink

0

I have a COM object, implemented in a C# .dll, named ComClass which sources events. Then, I have a C++ object, SimpleSink, that sinks the events sent from ComClass. The event source/sink mechanism works great. But, when the CRT calls exit(), I'm getting a memory access exception thrown from the following code in exe_common.inl

    //
    // main has returned; exit somehow...
    //

    if (!__scrt_is_managed_app())
        exit(main_result); // Exception is thrown.

The text of the exception message is as follows.

Exception thrown at 0x00000004 in Cpp.exe: 0xC0000005: Access violation executing location 0x00000004.

I understand that something is attempting to access a junk memory location, but I'm unsure as to what. I researched the issue and I came across this, from Microsoft.

https://msdn.microsoft.com/en-us/library/ms235234.aspx

Once the common language runtime (CLR) enters shutdown mode, native functions have limited access to CLR services. When attempting to call Release on a COM object compiled with /clr, the CLR transitions to native code and then transitions back into managed code to service the IUnknown::Release call (which is defined in managed code). The CLR prevents the call back into managed code since it is in shutdown mode.

I'm not sure if this is applicable only to C++ /clr compiled COM objects, or all CLR compiled COM objects. It may be a cold lead, so to speak. I understand that I could disable the exception and 'probably' go about my business, but that makes me feel oily. So, the question is, how can I prevent this exception when my program shuts down?

Here it is.

int main()
{
    CoInitialize(NULL);

    // explicit scope so that the smart pointer destructs at the correct time
    {
        IComClassPtr source;
        HRESULT createInstance = source.CreateInstance(__uuidof(ComClass));

        SinkSimple sink;

        HRESULT advise = sink.DispEventAdvise(source);

        try
        {
            source->FireEvent();
        }
        catch (const _com_error& ex)
        {
            std::cout << "Error: " << ex.Description();
        }

        HRESULT unadvise = sink.DispEventUnadvise(source);
    }    

    CoUninitialize();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    return 0;
}
c#
c++
com
com-interop
atl
asked on Stack Overflow Aug 20, 2017 by John Stritenberger • edited Aug 23, 2017 by John Stritenberger

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0