Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams 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;

The problem is that the following code raises segfault:

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;

But if I put GetNearest code in constructor (so that I construct index and find pt's neighbor in constructor itself), or just write constructor and GetNearest code in main, then everything works just fine.

I am new to nanoflann, can't figure what's wrong. Thanks for the help in advance!

I had to dig into the source nanoflann.hpp to find that the second parameter to the constructor for KDTreeSingleIndexAdaptor (cloud in your KdTree constructor) is passed by reference and stored as a reference. This means that the cloud data you pass to nanoflann needs to stay around until you delete the KDTreeSingleIndexAdaptor object.

Because you declare PointCloud cloud as a local variable within your KdTree constructor, it will be destroyed when the constructor ends leaving the kdtree pointed to by index with an dangling internal reference.

One solution is to make cloud a member of KdTree.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.