3

我的MEX 文件是用 C++/CLI 编写的,并调用了一个用 C# 编写的 DLL。

当 gcnew 一个对象时,当 mexFunction 返回时它不应该被垃圾收集吗?它的引用应该会丢失,但似乎没有任何东西被垃圾收集......每次调用 mex 函数都会增加MATLAB的内存分配(不,内存不用于 MATLAB 变量)。

我已经尝试过创建一个范围很窄的大型虚拟值,并且在单步执行 MEX 文件时,我可以看到分配和释放的内存。但在 mexFunction =(

我试图在析构函数和终结器中删除它,但我无法让它进行垃圾收集。返回 MATLAB 时如何释放托管内存?

我认为外部 DLL 文件管理器不是问题。为了说明,我创建了这个愚蠢的 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();
}

这使 MATLAB 的内存增加了大约 300 MB,尽管后续调用不会像我的真实 MEX 文件那样进一步增加内存。

编辑:

我回答了我自己的问题,罪魁祸首是mxArrayToString

4

2 回答 2

2

垃圾收集将内存标记为在 .NET 堆内可用。它不会缩小 .NET 堆(这会使内存对其他进程可用,而地址空间对进程中的非 .NET 代码可用)。

它明确记录了大对象堆永远不会缩小,一个包含 1000 万个条目的字典可能大到足以进入 LOH。

于 2012-09-19T20:14:03.600 回答
2

我发现了问题,结果它毕竟与 .net 无关……对不起那个红鲱鱼

由于我没有使用 new、malloc 或 mxMalloc,我错误地认为我所有的非托管内存都在堆栈中,并在 mexFunction 结束时被清理。

但是,mxArrayToString 不会像 mxGetData 和其他 mx* 函数那样返回指向 MATLAB 数据的指针。它将数据复制到堆上,并且必须调用 mxFree 来释放它。我使用 mxArrayToString 作为输入来创建 System::String^,唯一需要的更改是保存临时字符指针,将其用于 String^ 构造函数,然后 mxFree。

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

于 2012-09-26T09:09:10.550 回答