1

すでに少なくとも 12 のvalgrind reports invalid read質問があることは承知していますが、ご容赦ください。なぜなら、どうすればよいか分からないので、あなたの質問をお願いしたいからです。

私は、OpenCV 機能検出および機能説明モジュールのラッパーを作成しています (ある時点で、独自の機能検出/抽出を実装できるようにしたいと考えています)。そのため、OpenCV データ型を直接操作することはできません。

そのため、機能から記述子を抽出するときは、std::vector <std::vector <double> >ではなくとして保存しますcv::Mat。最初に記述子を計算し、それらをある表記から別の表記に変換するこのコードがあります。

// private
void CVDescriptor::calculateDescriptors(std::vector <cv::KeyPoint> &feats){
    this->feats = &feats;
    this->descCalc->compute(*(this->image), feats, this->desc);
    this->calculated = true;  
}

// public
void CVDescriptor::calculateDescriptors
                         (std::vector< std::vector< double > >& desc,
                          std::vector< cv::KeyPoint >& feats){    

    if (!this->calculated)
        this->calculateDescriptors(feats);

    assert(this->calculated);

    const double *temp;
    desc.clear();
    desc.reserve(this->desc.rows);
    for (int i=0, szi = this->desc.rows; i < szi; ++i){
        temp = this->desc.ptr<double>(i);

        // this line is the problem
        desc.push_back(std::vector<double>(temp, temp+(this->desc.cols)));
        //  .
        // /|\
        //  |
    }

    assert(desc.size() == this->desc.rows);
    assert(desc[0].size() == this->desc.cols);
    return;
}

これが私のメンバー変数のタイプです。私はそれらを初期化する場所をチェックして書きました(混乱を避けるためだけに):

std::vector <cv::KeyPoint> *feats
cv::Mat *image;
    // it is set just before calling calculateDescriptors(desc, feats)
cv::Mat desc;
bool calculated; // set in the only constructor

OpenCV ドキュメントは次のとおりですcv::DescriptorExtractor::compute。私が見る限り、計算された各記述子は の 1 つの行であるcv::Mat必要があり、マトリックスの列と同じ数のコンポーネントを持っている必要があります。


コードのいくつかの場所でメモリ リークが疑われるため、Valgrindで実行しました。最初に報告Invalid read of size 1されるのは、コードの抜粋で大きな矢印でマークされた行です。私が見る限りCVDescriptor::calculateDescriptors(..)、 のすべての反復ではなく、 への呼び出しごとに 2 回だけ報告していますfor loop

私のコピーコードに明らかに問題があることを誰かが見ることができますか? または、これがどのように起こっているのか、他のアイデアはありますか?

必要に応じて追加情報を提供できますが、関連するすべてのコードをここに配置しようとしました (私のプロジェクトはかなり大きいため)。よろしくお願いします(長い質問で申し訳ありません)...

4

1 に答える 1

1

反復ごとにコピーされるメモリブロックの開始アドレスと終了アドレスの出力を追加したところ、問題が明らかになりました。印刷物からの抜粋:

copied from 0xc0d5990 -- 0xc0d5d90
copied from 0xc0d5b90 -- 0xc0d5f90
copied from 0xc0d5d90 -- 0xc0d6190
copied from 0xc0d5f90 -- 0xc0d6390
copied from 0xc0d6190 -- 0xc0d6590

すべての反復でcv::Matdouble格納されているデータがfloat.

として宣言tempし、割り当てconst float *temp;を変更するtemp

temp = this->desc.ptr<float>(i);

トリックを行います。

于 2012-06-13T10:12:42.860 に答える