qsort 的比较仿函数的分段错误
Segmentation fault at qsort's compare functor
我有以下结构,由指向下一个点的指针 (nextPoint)、点的高度 (realHeight) 和来自 OpenCV 库的 3D 坐标 (point),它有 3 个参数 (x,y,z) :
typedef struct _cloudPoint {
double realHeight;
cv::Point3f point;
_cloudPoint* nextPoint;
} cloudPoint;
然后,我需要对 cloudPoint 的向量进行排序,我通过指向函数的指针传递该向量。所以我有这个函数的输入参数:
std::vector<cloudPoint>* cPointsVector
在我的函数中,我希望使用 qsort 对 cPointsVector 向量进行排序,这个比较仿函数:
int cmp_unique(const void* _pa_, const void* _pb_) {
Segmentation::cloudPoint* pa = (Segmentation::cloudPoint*)_pa_;
Segmentation::cloudPoint* pb = (Segmentation::cloudPoint*)_pb_;
if (pa->point.x > pb->point.x) {
return -1;
}
else {
if (pa->point.y > pb->point.y) {
return -1;
}
else {
if (pa->point.z > pb->point.z) {
return -1;
}
}
}
return 1;
}
所以,调用 qsort 我使用:
qsort(cPointsVector, cPointsVector->size(), sizeof(cloudPoint), cmp_unique);
但是在排序过程的中间,如果 :
if (pa->point.x > pb->point.x) {
通过分析我的代码,或者我在比较仿函数中执行了一些不正确的内存访问,或者 cPointsVector 被错误地填充,但是假设都没有意义,因为我总是使用非 Null 的 cloudPoint,与非空 OpenCV 坐标点.
提前致谢
试着这样称呼它:
qsort(&(*cPointsVector)[0], cPointsVector->size(), sizeof(cloudPoint), cmp_unique);
或
qsort(cPointsVector->data(), cPointsVector->size(), sizeof(cloudPoint), cmp_unique);
当您将 cPointsVector
传递给 qsort 时,您传递的是指向向量对象的指针,而不是指向向量第一个元素的指针。请记住,C++ 中的向量不是 C 数组。它是一个对象,封装了一个 C 数组,该数组的地址与向量的地址不同。
即使您想使用 qsort
,这也是您最终应该使用 std::sort
完成排序的方式:
std::sort(cPointsVector->begin(), cPointsVector->end(),
[](Segmentation::cloudPoint* s1, Segmentation::cloudPoint *s2)
{
return std::tie(s1->point.x, s1->point.y, s1->point.z) >
std::tie(s2->point.x, s2->point.y, s2->point.z);
});
请注意,没有完成 C 风格的转换,因为 std::sort
是类型安全的。
lambda 函数基本上执行您的 qsort
比较试图执行的操作,即按 (x,y,z)
降序排序。
std::tie 是执行级联 if
语句的简单方法,将 x
与 x
、y
进行比较与 y
等
我有以下结构,由指向下一个点的指针 (nextPoint)、点的高度 (realHeight) 和来自 OpenCV 库的 3D 坐标 (point),它有 3 个参数 (x,y,z) :
typedef struct _cloudPoint {
double realHeight;
cv::Point3f point;
_cloudPoint* nextPoint;
} cloudPoint;
然后,我需要对 cloudPoint 的向量进行排序,我通过指向函数的指针传递该向量。所以我有这个函数的输入参数:
std::vector<cloudPoint>* cPointsVector
在我的函数中,我希望使用 qsort 对 cPointsVector 向量进行排序,这个比较仿函数:
int cmp_unique(const void* _pa_, const void* _pb_) {
Segmentation::cloudPoint* pa = (Segmentation::cloudPoint*)_pa_;
Segmentation::cloudPoint* pb = (Segmentation::cloudPoint*)_pb_;
if (pa->point.x > pb->point.x) {
return -1;
}
else {
if (pa->point.y > pb->point.y) {
return -1;
}
else {
if (pa->point.z > pb->point.z) {
return -1;
}
}
}
return 1;
}
所以,调用 qsort 我使用:
qsort(cPointsVector, cPointsVector->size(), sizeof(cloudPoint), cmp_unique);
但是在排序过程的中间,如果 :
if (pa->point.x > pb->point.x) {
通过分析我的代码,或者我在比较仿函数中执行了一些不正确的内存访问,或者 cPointsVector 被错误地填充,但是假设都没有意义,因为我总是使用非 Null 的 cloudPoint,与非空 OpenCV 坐标点.
提前致谢
试着这样称呼它:
qsort(&(*cPointsVector)[0], cPointsVector->size(), sizeof(cloudPoint), cmp_unique);
或
qsort(cPointsVector->data(), cPointsVector->size(), sizeof(cloudPoint), cmp_unique);
当您将 cPointsVector
传递给 qsort 时,您传递的是指向向量对象的指针,而不是指向向量第一个元素的指针。请记住,C++ 中的向量不是 C 数组。它是一个对象,封装了一个 C 数组,该数组的地址与向量的地址不同。
即使您想使用 qsort
,这也是您最终应该使用 std::sort
完成排序的方式:
std::sort(cPointsVector->begin(), cPointsVector->end(),
[](Segmentation::cloudPoint* s1, Segmentation::cloudPoint *s2)
{
return std::tie(s1->point.x, s1->point.y, s1->point.z) >
std::tie(s2->point.x, s2->point.y, s2->point.z);
});
请注意,没有完成 C 风格的转换,因为 std::sort
是类型安全的。
lambda 函数基本上执行您的 qsort
比较试图执行的操作,即按 (x,y,z)
降序排序。
std::tie 是执行级联 if
语句的简单方法,将 x
与 x
、y
进行比较与 y
等