none
C++.NET with AppDomain. OutOfMemoryException? RRS feed

  • Question

  • Hi,

    I have a C++.NET assembly that necessarily has to load another assembly into an AppDomain and create the object from there.

    But I have a method that accesses a property on the remote object that returns a string array, which is called multiple times through the lifetime of the application.

    Except that after a few attempts, I get an OutOfMemoryException.

    Initial code to load domain:

    TCHAR tmpModulePath[MAX_PATH];
    GetModuleFileName(GetModuleHandle(L"My.dll"), tmpModulePath, MAX_PATH);
    
    String^ modulePath = Marshal::PtrToStringAuto(static_cast<IntPtr>(tmpModulePath));
    modulePath = System::IO::Path::GetDirectoryName(modulePath);
    
    AppDomainSetup^ ads = gcnew AppDomainSetup();
    ads->ConfigurationFile = System::IO::Path::Combine(modulePath, L"Wrapper.dll.config");
    ads->ApplicationBase = modulePath;
    _domain = AppDomain::CreateDomain(L"MyDomain", nullptr, ads);

    And to create object:

    System::Type^ t = MyObject::typeid;
    return (MyObject^)_domain->CreateInstanceAndUnwrap(t->Assembly->FullName, L"Wrapper.MyObject");

    The above should only be running once. But then I have this method:

    MyObject^ speller = GetMyObject();
    
    array<String^>^ words = speller->Words;

    Its the last line that eventually blows up. The array returned by the Words property never contains more than 2 or 3 strings.

    I have changed the code inside the remote object so that speller->Words does nothing exciting other than returning a straightforward array rather than any real functionality (to eliminate some 3rd-party code from the issue) and the problem still occurred.

    However if I change the access code to:

    array<String^>^ words = gcnew array<String^>{"1", "2", "3"};

    So it's not accessing the remote object at all, then the problem goes away.

    None of the objects involved are disposable, but am I missing some memory trick?




    • Edited by RJP1973 Wednesday, October 23, 2019 3:48 PM
    Wednesday, October 23, 2019 3:45 PM

Answers

  • Thanks for the advice and, forgive me, I think the issue was actually somewhere else after all!

    Just before the code that passes the array back, it calls a function to create and initialise a 3rd-party object if needed. This other object was not disposable therefore I didn't make my own MarshalByRefObject disposable either.

    Except I believe this other object was using up some resource or locking a file or something somewhere. And this, for some reason, led to an OutOfMemoryException being thrown eventually (only after a few attempts), even though I also believe the exception to be slightly spurious.

    I have now made my own object Disposable and use the Dispose() method to remove some items from collection properties in the 3rd-party object etc and, fingers crossed, think that has fixed the issue.

    I hope.

    • Marked as answer by RJP1973 Thursday, October 24, 2019 9:54 AM
    Thursday, October 24, 2019 9:54 AM

All replies

  • I don't see an obvious problem with your code.
    But is there a good reason to use a separate AppDomain?
    When the C++ assembly is calling unmanaged code this might result in unexpected behaviour.
    (speaking out of experience)

    I don't know which Visual Studio version you are using, but the built in profiler should give you a good grasp of what is allocated: "Debug - Performance Profiling - .NET Object Allocation Tracking"
    or "Debug - Performance Profiling - Memory Usage"
    • Edited by EckiS Wednesday, October 23, 2019 5:52 PM
    Wednesday, October 23, 2019 5:52 PM
  • Thanks for the advice and, forgive me, I think the issue was actually somewhere else after all!

    Just before the code that passes the array back, it calls a function to create and initialise a 3rd-party object if needed. This other object was not disposable therefore I didn't make my own MarshalByRefObject disposable either.

    Except I believe this other object was using up some resource or locking a file or something somewhere. And this, for some reason, led to an OutOfMemoryException being thrown eventually (only after a few attempts), even though I also believe the exception to be slightly spurious.

    I have now made my own object Disposable and use the Dispose() method to remove some items from collection properties in the 3rd-party object etc and, fingers crossed, think that has fixed the issue.

    I hope.

    • Marked as answer by RJP1973 Thursday, October 24, 2019 9:54 AM
    Thursday, October 24, 2019 9:54 AM