简体   繁体   中英

Memory leak in MATLAB > MEX file > managed DLL

My MEX file is written in C++/CLI and calls a DLL written in C#.

When gcnew'ing an object, shouldn't it be garbage collected when the mexFunction returns? Its references should be lost but nothing seems to be garbage collected... each call to the mex function increases MATLAB 's memory allocation (and no, the memory is not used for MATLAB variables).

I've experimented with creating a large dummy value with narrow scope and when stepping through the MEX file I can see the memory allocated and released. But not so with the main object created in the mexFunction =(

I've tried to delete it in the destructor and finalizer, but I can't get it to garbage collect. How can I free the managed memory when returning to MATLAB?

I don't think external DLL filers are the problem. To illustrate, I created this silly mexFunction:

public ref class Foo
{
    public:
        Foo()
        {
            Dictionary<int,String^>^ bar = gcnew Dictionary<int,String^>;
            for(int i=0;i<10000000;i++)
            {
                bar->Add(i, "abcdefghijklmnopqrstuvxyz");
            }
        }
};

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, mxArray* prhs[])
{
    Foo^ test = gcnew Foo();
}

This bumps MATLAB's memory by around 300 MB, although subsequent calls don't increase the memory further like in my real MEX file.

EDIT:

I answered my own question, the culprit was mxArrayToString

Garbage collection marks the memory as available inside the .NET heap. It doesn't shrink the .NET heap (which would make the memory available to other processes and the address space available to non .NET code within your process).

It's explicitly documented that the Large Object Heap is never shrunk, and a Dictionary with 10 million entries is probably large enough to go onto the LOH.

I found the problem, turns out it wasn't .net related after all... sorry for that red herring

Since I wasn't using new, malloc or mxMalloc I wrongly assumed that all my unmanaged memory would be in the stack and cleaned up when the mexFunction ended.

However mxArrayToString doesn't return a pointer to the MATLAB data as mxGetData and other mx* functions do. It copies the data onto the heap and one has to call mxFree to release it. I used mxArrayToString as input to create a System::String^, the only change needed was to save a temporay char pointer, use that for the String^ constructor and then mxFree it.

So once again for SEO: The pointer from mxArrayToString needs to be mxFree'd !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM