我的MEX file是用C ++ / CLI编写的,并调用用C#编写的DLL。
当gcnew'ing一个对象时,当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
答案 0 :(得分:2)
垃圾收集将内存标记为.NET堆中可用的内存。它不会缩小.NET堆(这将使内存可用于其他进程以及可用于进程中非.NET代码的地址空间)。
明确记载大型对象堆永远不会缩小,而拥有1000万条目的词典可能足以进入LOH。
答案 1 :(得分:2)
我发现了问题,结果发现它毕竟不是.net相关...对不起那个红鲱鱼
由于我没有使用new,malloc或mxMalloc,我错误地认为所有非托管内存都在堆栈中并在mexFunction结束时清理。
但是mxArrayToString不会像mxGetData和其他mx *函数那样返回指向MATLAB数据的指针。它将数据复制到堆上,并且必须调用mxFree来释放它。我使用mxArrayToString作为输入来创建System :: String ^,唯一需要的更改是保存临时字符指针,将其用于String ^构造函数然后mxFree它。
再一次对SEO:来自 mxArrayToString 的指针需要 mxFree&#39; d !