2011-11-14 26 views
3

次のコードを使用すると、メモリがかなり高速になります。 Valgrindはメモリリークを示していますが、関数が終了するとすべてがスタックに割り当てられ、解放されるはずです。OpenCV Matを作成するとメモリリークが発生する

void mult_run_time(int rows, int cols) 
{ 
    Mat matrix(rows,cols,CV_32SC1); 
    Mat row_vec(cols,1,CV_32SC1); 

    /* initialize vector and matrix */ 
    for (int col = 0; col < cols; ++col) 
    { 
     for (int row = 0; row < rows; ++row) 
     { 
      matrix.at<unsigned long>(row,col) = rand() % ULONG_MAX; 
     } 

     row_vec.at<unsigned long>(1,col) = rand() % ULONG_MAX; 
    } 
    /* end initialization of vector and matrix*/ 

    matrix*row_vec; 
} 

int main() 
{ 
    for (int row = 0; row < 20; ++row) 
    { 
     for (int col = 0; col < 20; ++col) 
     { 
      mult_run_time(row,col); 
     } 
    } 

    return 0; 
} 

Valgrindのは、ラインMat row_vec(cols,1,CV_32CS1)でメモリリークがあることを示しています

==9201== 24,320 bytes in 380 blocks are definitely lost in loss record 50 of 50 
==9201== at 0x4026864: malloc (vg_replace_malloc.c:236) 
==9201== by 0x40C0A8B: cv::fastMalloc(unsigned int) (in /usr/local/lib/libopencv_core.so.2.3.1) 
==9201== by 0x41914E3: cv::Mat::create(int, int const*, int) (in /usr/local/lib/libopencv_core.so.2.3.1) 
==9201== by 0x8048BE4: cv::Mat::create(int, int, int) (mat.hpp:368) 
==9201== by 0x8048B2A: cv::Mat::Mat(int, int, int) (mat.hpp:68) 
==9201== by 0x80488B0: mult_run_time(int, int) (mat_by_vec_mult.cpp:26) 
==9201== by 0x80489F5: main (mat_by_vec_mult.cpp:59) 

それはOpenCVのでは既知のバグですか、私は何かが足りないのですか?ランド()はとにかくintengerを返し、そう合計範囲には利得がないので、代わりにunsigned int型を使用するため

+2

これは無関係かもしれないが、あなたは 'CV_32SC1'は'符号なしlong'であることを確信しているが?彼らは私にとって 'int 'のように見えます...(実際に許されていないメモリスペースに書き込むのは、unsigned longがintよりもビット数が多いためです) – Fezvez

+0

Fezvezが正しいです割り当てられていないメモリを実際に書き込みます。結果は予想外です。 – Sam

+0

'unsigned long'を' int'に、 'ULONG_MAX'を' INT_MAX'に変更しました。 Mem-leakが残っています。 –

答えて

1

長い

matrix.at<unsigned long>(row,col) = rand() % ULONG_MAX; 

で符号なしの使用に無駄がありません。ラインで

row_vec.at<unsigned long>(1,col) = rand() % ULONG_MAX; 

あなたが範囲外のインデックスにアクセスしています。 C++では、ベクトルは0ではなく1から始まります。そして、行列はopencvで行ごとに格納されます。あなたは割り当てられていないメモリ領域を処理しています、それはおそらくvalgrindがメモリリークを検出している理由です。用途:

row_vec.at<unsigned int>(col, 0) = rand() % ULONG_MAX; 

私はそれが場合だったらならば、OpenCVのは、あなたがベクトルの合計範囲内であることを確認するために、インデックスにアクセスする前にアサーションを使用していますので、あなたがデバッグモードでプログラムをコンパイルしていないことを前提としあなたがデバッグモードでコンパイルしていた場合、あなたのプログラムはコードの実行中にアサーションの失敗を投げ、この種の間違いを追跡しやすくなります。デバッグモードでコードをプロトタイプ作成することをお勧めします。

+0

ああクールなthnx ...そして、あなたが正しいと思います。初めてOpenCVをコンパイルしたときは、 'CMAKE_BUILD_TYPE = RELEASE'であった。フラグをDEBUGに変更してOpenCVを再コンパイルすると、リリースのものと一緒にデバッグライブラリがビルドされ、モードをコンパイルするように定義できますか? –

+0

ビルド済みのバイナリ([link](http://sourceforge.net/projects/opencvlibrary/files/))を使用する代わりに、コードを再コンパイルする唯一の理由は、EIGENのような3番目のライブラリの使用をセットアップすることです[リンク](http://eigen.tuxfamily.org/))。そうでない場合は、あらかじめ作成されたバイナリをすぐに使用できます。彼らにはすでにデバッグライブラリファイルが付属しており、それらにリンクするだけでアサーションの失敗がスローされます。デバッグ時にOpenCVコードを実行したい場合は、デバッグフラグを付けて再コンパイルする必要があります。 (まあ、別の理由がある...) –

0

@IanMedeirosと部分的に同意します:ここでは、適切なキャストunsigned intです。

実際にはの場合タイプのマットがありますただ1つ正しいキャストです。 リストチェックの場合this answer here。 答えは、グレースケール画像の正しいキャストを直ちに与えます。 マルチチャンネルの画像の場合

あなたはVec<mat_type, num_channels>にキャストする必要があります。

最も一般的な定義済みのVecとのopencv2 libにから:

typedef Vec<uchar, 3> Vec3b; // this is how a color image gets usually loaded 
typedef Vec<short, 3> Vec3s; 
typedef Vec<ushort, 3> Vec3w; 
typedef Vec<int, 3> Vec3i; 
typedef Vec<float, 3> Vec3f; 
typedef Vec<double, 3> Vec3d; 
関連する問題