Nanoflann findNeighbors 引发段错误

Nanoflann findNeighbors raise segfault

所以我有以下 class 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 的邻居),或者只在构造函数和 GetNearest 中编写代码main,然后一切正常。

我是 nanoflann 的新手,不知道哪里出了问题。提前感谢您的帮助!

我不得不深入研究源代码 nanoflann.hpp,发现 KDTreeSingleIndexAdaptor 的构造函数的第二个参数(KdTree 构造函数中的 cloud )由参考和 stored 作为参考。这意味着您传递给 nanoflann 的云数据需要保留,直到您删除 KDTreeSingleIndexAdaptor 对象。

因为您在 KdTree 构造函数中将 PointCloud cloud 声明为局部变量,所以当构造函数结束时它会被销毁,从而使 index 指向的 kdtree 带有悬垂的内部引用.

一个解决方案是让 cloud 成为 KdTree 的成员。