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::compute
的OpenCV文档。据我所知,每个计算的描述符应该是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);
能解决问题。
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 使用strcpy将char数组的元素复制到另一个数组
- 是否可以初始化不可复制类型的成员变量(或基类)
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 复制列表初始化的隐式转换的等级是多少
- Android NDK传感器向事件队列报告奇怪的间隔
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- 使用std::source_location报告错误的最佳实践
- 当从函数参数中的临时值调用复制构造函数时
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 复制几乎为空的数组的最快方法
- xmake总是报告:错误:无法获取cxx的程序,为什么
- 当用户超过按钮点击限制时报告
- 以下示例中如何避免代码复制?C++/库达
- 使用调试/崩溃报告将应用程序部署到客户端
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- OpenCV 提取的描述符会导致 valgrind 在被复制时报告无效读取