外部インタフェース/API | ![]() ![]() |
MEX-ファイル内でのメモリ管理は、通常のCまたはFortranアプリケーションのメモリ管理とは異なります。しかし、MEX-ファイルがMATLAB自体のような大きいアプリケーション内に存在する必要があるため、考慮すべきことがあります。
MEX-ファイルがMATLABに戻るとき、左辺引数の形式(plhs[]
リストに含まれるmxArray
)で計算の結果をMATLABに与えます。このリストにないMEX-ファイルによって作成されたmxArray
は、自動的に破棄されます。さらに、MEX-ファイルの実行中にmxCalloc
, mxMalloc
, mxRealloc
を使って割り当てられたメモリは、自動的に開放されます。
一般に、MEX-ファイルがテンポラリ配列を破棄し、ダイナミックに割り当てられたメモリを開放することを推奨します。自動メカニズムに依存するよりも、MEX-ファイルがこのクリーンアップを行うほうが効率的です。しかし、MEX-ファイルが標準のリターンステートメントに至らない状況があります。以下の場合には標準のリターンに達しません。
mexErrMsgTxt
の呼び出しの発生mexCallMATLAB
の呼び出しが発生し、呼び出された関数がエラーを出力するとき(MEX-ファイルは、mexSetTrapFlag
を使ってそのようなエラーをトラップしますが、すべてのMEX-ファイルが必ずしもエラーをトラップする必要があるわけではありません)。注意深いMEX-ファイルプログラマは、最初の2つの場合になる前に、すべてのテンポラリ配列とメモリを確実にクリーンアップするかもしれませんが、最後の2つの場合はしないかもしれません。後の2つの場合では、メモリリークを避けるために自動クリーンアップメカニズムが必要です。
固定配列
mexMakeArrayPersistent
またはmexMakeMemoryPersistent
を呼び出すことによって、MATLABの自動クリーンアップから配列またはメモリの一部を外すことができます。しかし、MEX-ファイルがそのような固定オブジェクトを作成する場合、固定オブジェクトが適切に破棄される前に、MEX-ファイルが消去される場合は、メモリリークが発生するという危険があります。この発生を避けるために、固定オブジェクトを作成するMEX-ファイルは、オブジェクトを破棄する関数mexAtExit
を使って関数を登録するべきです(関数mexAtExit
を使ってその他のリソースを破棄することも可能です。たとえば、mexAtExit
を使ってオープンしているファイルをクローズできます)。
たとえば、以下に示すのは固定配列を作成し、適切に破棄する簡単なMEX-ファイルです。
#include "mex.h" static int initialized = 0; static mxArray *persistent_array_ptr = NULL; void cleanup(void) { mexPrintf("MEX-file is terminating, destroying array\n"); mxDestroyArray(persistent_array_ptr); } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (!initialized) { mexPrintf("MEX-file initializing, creating array\n"); /* Create persistent array and register its cleanup. */ persistent_array_ptr = mxCreateDoubleMatrix(1, 1, mxREAL); mexMakeArrayPersistent(persistent_array_ptr); mexAtExit(cleanup); initialized = 1; /* Set the data of the array to some interesting value. */ *mxGetPr(persistent_array_ptr) = 1.0; } else { mexPrintf("MEX-file executing; value of first array element is %g\n", *mxGetPr(persistent_array_ptr)); } }
ハイブリッド配列
mxSetPr
, mxSetData
, mxSetCell
のような関数を使って、メモリの一部をmxArray
に直接配置することができます。mxDestroyArray
は、配列全体に加えてこれらの部分を破棄します。このため、破棄されない配列、すなわちmxDestroyArray
を確実に呼び出さない配列を作成することができます。そのような配列は、破棄可能な部分と破棄不可能な部分の両方を含むため、ハイブリッド 配列と呼ばれます。
たとえば、自動変数に対してmxFree
(またはANSI関数free()
を呼び出すことは有効ではありません。そのため、以下のコードでpArray
はハイブリッド配列です。
mxArray *pArray = mxCreateDoubleMatrix(0, 0, mxREAL); double data[10]; mxSetPr(pArray, data); mxSetM(pArray, 1); mxSetN(pArray, 10);
ハイブリッド配列のその他の例は、子のうちの1つが参照のみの配列(MEX-ファイルの入力のような修飾const
をもつ配列)であるセル配列または構造体です。MEX-ファイルへの入力も破棄されるため、配列は破棄できません。
ハイブリッド配列は破棄できないので、「テンポラリ配列の自動クリーンアップ」で記述した自動メカニズムによってクリーンアップできません。そこで記述したように、自動クリーンアップメカニズムは、ユーザ割り込みの場合にテンポラリ配列を破棄する唯一の方法です。そのため、テンポラリハイブリッド配列は無効であり MEX-ファイルがクラッシュする場合があります。
固定ハイブリッド配列は実行可能であっても、可能な限り利用を避けることを推奨します。
![]() | アドバンスドトピックス | LAPACKおよびBLAS関数の使用法 | ![]() |