Memory leak in MATLAB > MEX file > managed DLL

2019-05-11 05:12发布

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

2条回答
做自己的国王
2楼-- · 2019-05-11 05:57

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.

查看更多
Bombasti
3楼-- · 2019-05-11 06:16

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!

查看更多
登录 后发表回答