Nanoflann Kdtree适配器提高了Segfault
nanoflann kdtree adaptor raises segfault
我正在尝试在我的类中使用nanoflann的kdtree结构。我有以下针对KDTREE适配器的标头,这只是其中的一个很小(可能是不好的(变化,应该允许具有3D向量的Kd-Tree结构作为元素:
// "KdVec3dAdaptor.h"
#include "nanoflann.hpp"
#include <vector>
using Distance = nanoflann::metric_L2; // Was in template before, dont need it, this way its easier to read
using VectorOfVectorsType = std::vector<std::array<double,3>>;
template <class VectorOfVectorsType>
struct KdVec3dAdaptor
{
typedef KdVec3dAdaptor<VectorOfVectorsType> self_t;
typedef typename Distance::template traits<double,self_t>::distance_t metric_t;
typedef nanoflann::KDTreeSingleIndexAdaptor< metric_t,self_t,3,size_t> index_t;
VectorOfVectorsType m_data;
index_t* index; //! The kd-tree index for the user to call its methods as usual with any other FLANN index.
KdVec3dAdaptor() = default;
KdVec3dAdaptor(const VectorOfVectorsType &mat, const int leaf_max_size = 10) : m_data(mat)
{
const size_t dims = mat[0].size();
index = new index_t( dims, *this /* adaptor */, nanoflann::KDTreeSingleIndexAdaptorParams(leaf_max_size ) );
index->buildIndex();
}
~KdVec3dAdaptor()
{ // destructor
delete index;
}
KdVec3dAdaptor& operator=(KdVec3dAdaptor&& other)
{ // move assignment operator
if (this != &other)
{ // check that no self-assignment is performed
delete index;
index = other.index;
m_data = other.m_data;
other.index = nullptr;
}
return *this;
}
const self_t & derived() const
{
return *this;
}
self_t & derived()
{
return *this;
}
inline size_t kdtree_get_point_count() const
{// Must return the number of data points
return m_data.size();
}
inline double kdtree_get_pt(const size_t idx, int dim) const
{ // Returns the dim'th component of the idx'th point in the class
return m_data[idx][dim];
}
template <class BBOX>
bool kdtree_get_bbox(BBOX & /*bb*/) const
{ // return false to default to a standard bbox computation loop.
return false;
}
};
我面临的问题是使用此KDTREE结构作为类的成员变量。所需类型定义的该类的最小版本是:
// "test.cpp"
#include <iostream>
#include <array>
#include "KdVec3dAdaptor.h"
const int dimens = 3;
using vec3d = std::array<double, dimens>;
using vec_arr = std::vector<vec3d>;
using my_kd_tree = KdVec3dAdaptor<vec_arr>;
class foo
{
public:
const int n;
const double level;
my_kd_tree init_ps_tree;
foo(const int &N, const double &level, vec_arr &kset)
:n(N), level(level)
{
init_ps_tree = my_kd_tree(kset,10);
}
};
这棵树以类的不同方法声明(我使用构成树点的Vec_arr类型的另一类变量(。现在,这是我在追踪错误而迷失的地方。当我尝试调用以下方法时:
void test()
{
double level = -0.3;
std::vector<double> arr1 {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1};
std::vector<double> arr2 {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1};
vec3d vec1 {{1.0, 0.0, 0.0}};
vec3d vec2 {{1.0, 0.0, 0.0}};
vec3d vec3 {{1.0, 0.0, 0.0}};
vec3d vec4 {{1.0, 0.0, 0.0}};
vec3d vec5 {{1.0, 0.0, 0.0}};
vec3d vec6 {{1.0, 0.0, 0.0}};
vec3d vec7 {{1.0, 0.0, 0.0}};
vec3d vec8 {{1.0, 0.0, 0.0}};
vec_arr vecarr1 {vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8};
int N = 5;
vec_arr init_points;
foo entity(N, level, kset);
std::cout << entity.n << std::endl;
}
我遇到了一个分割错误,我认为必须归因于KDTREE结构的标题。但是,我无法进一步追踪它,因为:
- 在主方法中执行完全相同的操作非常好,只有在其他地方完成此操作时才会出现错误
- 在不访问类实例的任何内容的情况下,代码可以编译好
- 删除任何未使用的VEC3D变量都可以解决该问题(您可以猜到,我以后在该方法中需要它们( (
- 即使有更多的成员变量,有时从类中删除其他成员变量(例如
level
或n
(也可以解决问题 - 使用
new
创建实例不会更改任何内容 - 摆脱班级中的任何成员变量可以解决问题(但实际上我需要项目中的其他地方(
我忽略了什么? KdVec3dAdaptor
中的驱动器是否有问题?我确定这一定是愚蠢的。预先感谢您的任何帮助和建议。
您正在删除未创建的对象。查看KdVec3dAdaptor
类的破坏者。在test
功能中,您创建了foo
对象
foo entity(N, level);
在此构造函数中,my_kd_tree init_ps_tree;
成员是通过使用未设置index
成员的KdVec3dAdaptor
的默认构造器创建的。当test
函数结束时,foo
destructor被调用并且init_ps_tree
被破坏,但未设置index
,
delete index;
在KdVec3dAdaptor
中,驱动器崩溃了您的程序。在KdVec3dAdaptor
的默认CTOR中,您应该将index
成员设置为0。
编辑
我不知道为什么您将默认构造函数的定义作为
KdVec3dAdaptor() = default;
在进入foo ctor
的主体之前,请查看foo
构造函数的定义
{
init_ps_tree = my_kd_tree(kset,10); // [1] init_ps_tree was already created
}
对象init_ps_tree
是通过使用默认构造函数创建的(index
成员可能包含垃圾数据 - 随机值,如果此对象的创建为本地变量(。在此行中[1]移动分配操作员被调用,将执行以下行
delete index; // very dangerous
您可以在Null指针上调用delete
,但是在您的情况下,我们不知道index
具有什么值。首先,将KdVec3dAdaptor
的CTOR写为
KdVec3dAdaptor::KdVec3dAdaptor() : index(0) {}
和下一件事,在您的移动分配运算符中,您应该使用std ::移动移动向量数据,现在已经制作了向量的副本。
if (this != &other)
{ // check that no self-assignment is performed
delete index;
index = other.index;
m_data = std::move(other.m_data); // [2] this vector can be moved
other.index = nullptr;
}
- C++中带有List类的迭代器Segfault
- 使用Vulkan hpp vk::enumerateInstanceVersion()会导致segfault
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- std::partition segfault issue
- OpenSSL: EC_POINT_set_compressed_coordinates_GFp segfault
- 检查nullptr是否100%保护内存布局不受segfault影响
- OpenCV Tracker 属性访问在 ARM 上因 SEGFAULT 而失败,但在 X86_64 中工作
- 为什么优化大型 std::vector 数组会导致 SegFault?
- C++segfault,可重复的例子
- 带有zip_source_buffer的libzip会导致数据损坏和/或segfault
- 导致SegFault C++的析构函数
- 从引用的Vector获取SEGFAULT
- 尝试读取/写入Graphviz DAG值的工作证明会导致segfault
- Segfault如果更改派生类的指针值
- SegFault deleting QTreeWidgetItem
- PyImport_Import segfault
- 添加#pragma循环后出现Segfault
- 使用 gmock 时的 SegFault
- C 多线程,在并行多个线程时获得SegFault
- Nanoflann Kdtree适配器提高了Segfault