Nanoflann发现邻居提出段错误

Nanoflann findNeighbors raise segfault

本文关键字:错误 段错误 发现 邻居 Nanoflann      更新时间:2023-10-16

所以我有以下类KdTree:

#include <nanoflann.hpp>
#include <ctime>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <cstdlib>
#include <iostream>
struct PointCloud
{
struct Point
{
double  x,y,z;
};
std::vector<Point>  pts;
inline size_t kdtree_get_point_count() const { return pts.size(); }
inline double kdtree_get_pt(const size_t idx, const size_t dim) const
{
if (dim == 0) return pts[idx].x;
else if (dim == 1) return pts[idx].y;
else if (dim == 2) return pts[idx].z;
}
template <class BBOX>
bool kdtree_get_bbox(BBOX& /* bb */) const { return false; }
};
void generatePointCloud(PointCloud &point, const std::vector<std::vector<double>>& given)
{
point.pts.resize(given.size());
for (size_t i = 0; i < given.size(); ++i) {
point.pts[i].x = given[i][0];
point.pts[i].y = given[i][1];
point.pts[i].z = given[i][2];
}
}
using namespace nanoflann;
using Points = std::vector<std::vector<double>>;
class KdTree {
public:
KdTree(const Points& points) {
PointCloud cloud;
generatePointCloud(cloud, points); // just puts points into cloud format
index = std::make_shared<my_kd_tree>(3 /*dim*/, cloud, KDTreeSingleIndexAdaptorParams(10 /* max leaf */) );
index->buildIndex();
}
size_t GetNearest(const std::vector<double>& pt) const {
double query_pt[3] = { pt[0], pt[1], pt[2] };
const size_t num_results = 1;
size_t ret_index;
double out_dist_sqr;
nanoflann::KNNResultSet<double > resultSet(num_results);
resultSet.init(&ret_index, &out_dist_sqr );
index->findNeighbors(resultSet, &query_pt[0], nanoflann::SearchParams(10));
std::cout << "knnSearch(nn="<<num_results<<"): n";
std::cout << "ret_index=" << ret_index << " out_dist_sqr=" << out_dist_sqr << endl;
return ret_index;
}
typedef KDTreeSingleIndexAdaptor<
L2_Simple_Adaptor<double , PointCloud > ,
PointCloud,
3 /* dim */
> my_kd_tree;
std::shared_ptr<my_kd_tree> index = nullptr;
};

问题是以下代码引发段错误:

int main()
{
srand(static_cast<unsigned int>(time(nullptr)));
Points points{{1, 5, 8}, {3, 3, 3}, {1, 1, 0}};
KdTree tree(points);
tree.GetNearest({1, 1, 1});
return 0;
}

但是如果我GetNearest代码放在构造函数中(以便我构造索引并在构造函数本身中找到pt的邻居(,或者只是编写构造函数并在 main 中GetNearest代码,那么一切正常。

我是纳米弗兰的新手,不知道出了什么问题。提前感谢您的帮助!

我不得不深入研究源 nanoflann.hpp 才能发现KDTreeSingleIndexAdaptor构造函数的第二个参数(cloud在您的KdTree构造函数中(是通过引用传递并存储为引用的。 这意味着您传递给 nanoflann 的云数据需要保留,直到您删除KDTreeSingleIndexAdaptor对象。

因为您将PointCloud cloud声明为KdTree构造函数中的局部变量,所以当构造函数结束时,它将被销毁,留下带有悬空内部引用的index指向的 kdtree。

一种解决方案是使cloud成为KdTree的成员。