2

私はMATLABで次のコードを書きました:

#include <string.h>
#include <stdlib.h>
#include "mex.h"
#include "matrix.h"

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[]){

    double* x = (double*)malloc(5 * sizeof(*x));
    int k;
    for(k=0;k<5;k++)
        x[k] = k;
    mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
    mxSetPr(p1, x);
}

入力も出力もなしで関数を呼び出します。コードは、いくつかのベクトルを初期化する以外は実際には何もしません。コードに深刻なメモリリークがあることは理解していますが、メモリリークは別として、関数を呼び出すと、MATLABが閉じます。

に置き換えるmallocmxMalloc、コードは問題なく実行されます。メモリの割り当てにmx*を使用することが望ましいことは理解していますが、MEXではmallocとcallocをfreeと一緒に問題なく使用できると確信しています。

(double *)も削除しましたが、それでもクラッシュします。

上記のコードでMATLABがクラッシュする理由を教えていただければ幸いです。ありがとう

4

3 に答える 3

6

まず最初に、(CではとにかくC ++は別の問題です)の戻り値をキャストしないでください。特にstdlib.hを含めない場合は、整数とポインタのサイズは異なります。malloc

キャストを外して、にを割り当てることについて文句を言うかどうかを確認しintますdouble *

含まれている場合は、プロトタイプstdlib.hを取得するために含めるようにしてください。malloc


いずれにせよ、ドキュメントは明確です:

アレイはダイナミックメモリにある必要があります。mxCallocこのメモリを割り当てるために呼び出します。ANSI C機能を使用しないでくださいcalloc。これにより、メモリアライメントの問題が発生し、プログラムが終了する可能性があります。

calloc具体的には関数についてのみ言及していますが、mxMallocドキュメントには次のように記載されています。

mxMallocnバイトを保持するのに十分な連続したヒープスペースを割り当てます。mxMallocANSI C関数の代わりに使用mallocして、MATLABアプリケーションでメモリを割り当てます。

したがって、あなたがしていることは、ドキュメントによって明示的に禁止されています。それをやめなさい。あそこに来させないでください:-)


詳細については、MatLabが高速計算のためにSIMDなどを使用していることについて多くの情報が浮かんでいます。

SIMDは、通常のCデータ型が必要とするものよりも厳密なアライメントを必要とする場合があります(したがって、malloc保証するものよりも厳密です)。

これが問題の原因である可能性があり、ドキュメントの「メモリアライメントの問題を引き起こす可能性がある」コメントによってサポートされています。これが当てはまるかどうかは完全にはわかりませんが(MatLabのソースコードにアクセスできないため)、少なくとも実行可能な説明です。

于 2013-02-27T02:03:18.727 に答える
2

投稿されたコードには、実際には2つの問題があります。

double* x = (double*)malloc(5 * sizeof(*x));
   :
mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
mxSetPr(p1, x); /* This leaks memory AND causes a crash */

最初の問題は、他の人がすでに投稿したものです。ネイティブC/C ++メモリ(malloc、calloc、realloc、newなど)をmxArrayに接続することはできません。これを行うと、MATLABメモリマネージャが台無しになり、MATLABがこのメモリを解放しようとすると、最終的にクラッシュが発生します。メモリーはMATLABAPI関数からmxArrayにのみアタッチできます。

2番目の問題は、メモリリークがあることです。mxCreateDoubleMatrix(5、1、mxREAL)呼び出しは、mxArrayのデータポインターの背後にメモリを割り当てます。このデータポインタはガベージコレクションリストにありません。その後mxSetPr(p1、x)を呼び出すと、そのデータポインタを消去してxに置き換えるため、そのデータポインタへの唯一のアクセスが失われ、メモリがリークします。このデータポインタはガベージコレクションリストにないため、mex関数が呼び出し元に戻ったときに解放されません。これは、MATLABを再起動することによってのみ回復できます。クラッシュを引き起こさず、メモリリークを引き起こさずにこれを適切にコーディングするいくつかの方法を次に示します。

元のデータポインタをmxMallocおよびmxFreeに変更します。

double* x = (double*)mxMalloc(5 * sizeof(*x));
   :
mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
mxFree(mxGetData(p1)); /* Free the original data pointer */
mxSetPr(p1, x); /* Attach MATLAB API generated pointer */

mxMallocに変更し、空行列から始めます。

double* x = (double*)mxMalloc(5 * sizeof(*x));
   :
mxArray* p1 = mxCreateDoubleMatrix(0, 0, mxREAL);
mxSetPr(p1, x); /* Attach MATLAB API generated pointer */
mxSetM(p1, 5); /* Set row size */
mxSetN(p1, 1); /* Set column size */

個別に割り当てるのではなく、元のデータポインタを使用してください。

mxArray* p1 = mxCreateDoubleMatrix(5, 1, mxREAL);
double* x = (double*)mxGetData(p1);
/* Then use x downstream in your code */
于 2021-01-06T17:55:30.613 に答える
0

他の誰かの潜在的な苦痛を節約するために、入力パラメーターxでmxMalloc(x)を使用する関数は、xが単にint xではなく、constintxとして宣言されている場合にのみ機能します。

于 2020-12-06T02:04:28.800 に答える