【问题标题】:Segmentation fault at qsort's compare functorqsort 的比较函子的分段错误
【发布时间】:2020-03-17 18:20:01
【问题描述】:

我有以下结构,由指向下一个点 (nextPoint) 的指针、点的高度 (realHeight) 和 3D 坐标 (point ) 来自 OpenCV 库,它有 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 的分段错误:

if (pa->point.x > pb->point.x) {

仅通过分析我的代码,或者我在比较函子中执行了一些不正确的内存访问,或者 cPointsVector 被严重填充,但假设都没有意义,因为我总是使用非 Null cloudPoint's,非空 OpenCV 坐标点。

提前致谢

【问题讨论】:

  • 你为什么不用std::sort
  • @PaulMcKenzie 因为我正在将我的一些代码从 c 升级到 c++,并希望在从 c 升级到 c++ 函数之前确保一切都按预期执行。你认为这可能是我问题的根源吗?我会切换并更新你的结果。
  • 几乎没有充分的理由使用指向vector 的指针。您可能对自己过于苛刻。建议:不要尝试像用 C 编程那样用 C++ 编程。这看起来很诱人,但它会给你带来更多的问题。
  • @Diogo -- 一看到qsort,就应该立即切换到std::sortstd::sort(cPointsVector.begin(), cPointsVector.end(), your_predicate);。无需强制转换,直观,运行速度可能比qsort 快。
  • 我使用指向向量的指针... -- C++ 有一个叫做reference 的东西,它在 C 中不存在。

标签: c++ vector struct segmentation-fault qsort


【解决方案1】:

试着这样称呼它:

qsort(&(*cPointsVector)[0], cPointsVector->size(), sizeof(cloudPoint), cmp_unique);

qsort(cPointsVector->data(), cPointsVector->size(), sizeof(cloudPoint), cmp_unique);

当您将cPointsVector 传递给 qsort 时,您传递的是指向向量对象的指针,而不是指向向量第一个元素的指针。请记住,C++ 中的向量不是 C 数组。它是一个对象,它封装了一个 C 数组,该数组的地址与向量的地址不同。

【讨论】:

  • 非常感谢,这非常有效。尽管如此,当我运行原始代码时,仿函数在分段错误之前执行了大约 300 次。为什么?
  • @Diogo 纯属运气。虽然程序在随机内存中肆虐,但它根本没有遇到任何导致崩溃的情况。最终导致程序崩溃的可能是它跑出了堆栈的末尾。永远不要指望崩溃。你在这里的术语是Undefined Behaviour,未定义行为的结果是,嗯,未定义。
  • @user4581301 感谢您的回答
  • 您应该使用std::sort() 提供适当的解决方案,这是一种解决方法,并且在使用非 POD 时可能很快就会出现 UB。
【解决方案2】:

即使您想使用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 语句的简单方法,将 xxyy 等进行比较。

【讨论】:

    猜你喜欢
    • 2015-05-22
    • 1970-01-01
    • 2021-10-01
    • 2014-10-10
    • 1970-01-01
    • 2020-12-15
    • 2018-03-26
    • 1970-01-01
    相关资源
    最近更新 更多