繁体   English   中英

OpenCV提取的描述符导致valgrind在复制时报告无效读取

[英]OpenCV extracted descriptors cause valgrind to report invalid read when being copied

我知道至少已经有十几个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

这是cv::DescriptorExtractor::computeOpenCV文档 从我可以看到,每个计算出的描述符在cv::Mat应该是一行,并且应该具有与矩阵中的列一样多的组件。


我怀疑代码中的某些地方存在内存泄漏,因此我通过Valgrind进行了运行。 它报告的第一件事是在代码摘录中用大箭头标记的行上的Invalid read of size 1 据我所知,它每次调用CVDescriptor::calculateDescriptors(..)仅报告两次,而不是在for loop每次迭代中报告两次。

有人能看到我的复制代码明显有问题吗? 还是有其他想法可能如何发生?

如果需要,我可以提供其他信息,但是我尝试将所有相关代码放在这里(因为我的项目很大)。 预先谢谢大家(对于冗长的问题,我深表歉意)...

我添加了在每次迭代中复制的内存块的起始地址和结束地址的打印输出,这揭示了问题所在。 摘录:

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

在每次迭代中,我不小心尝试一次复制cv::Mat两行,因为我是通过double指针访问它的,而存储的数据是float

temp声明为const float *temp; 并在其中更改temp分配

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

绝招。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM