std :: sort导致运算符中的分段错误<

时间:2020-05-26 12:46:24

标签: c++ sorting segmentation-fault

我正在尝试对3D整数矢量(std::vector)的列表(IntVec)进行排序。 std::sort以某种方式在operator<的{​​{1}}中引起分段错误。这是我的代码:

IntVec

我可以为您提供数据集;但是,我想首先查看我的代码中是否存在一些重大的概念性错误,或者是我没有看到的一些错误。我发现问题是特定于该数据集的。如果我遗漏一个条目,则不会发生Segfault。我认为这很奇怪,因为这样的错误应该更明显,并且与内存管理有关。还要注意,对#include <iostream> #include <algorithm> #include <vector> #include <fstream> struct IntVec { public: long x; long y; long z; // Using ints does not cause the Segmentation Fault ?! friend bool operator<(const IntVec &lhs, const IntVec &rhs) { return (lhs.z < rhs.z) || // Segmentation Fault happens here ((lhs.z == rhs.z) && (lhs.y < rhs.y)) || ((lhs.y == rhs.y) && (lhs.x < rhs.x)); } }; int main(void) { std::vector<IntVec> vec; const int N = 2178; std::ifstream s("res.txt"); for (int i = 0; i < N; i++) { IntVec t; s >> t.x; s >> t.y; s >> t.z; vec.push_back(t); } // Using vec.begin() and vec.end() does not change anything std::sort(vec.data(), vec.data() + vec.size()); } xy使用整数不会引起任何问题。

Here是该代码的精妙版本。

Here is a related SO question但是,我认为我的代码没有导致此错误的相同缺陷。我认为我的订购关系是“严格<”。

1 个答案:

答案 0 :(得分:10)

您的操作员逻辑已损坏(不满足严格的弱订购要求)。最后一个子句也需要lhs.z == rhs.z。否则,lhs.z可以是> rhs.z,但您仍会得到肯定的结果,从而导致顺序不一致。

标准库算法使您有责任做到这一点,打破结果假设很容易导致混乱(例如未定义的行为),例如分段错误。

想象一下实现中的注释,它说“现在,我们知道a小于b,所以我们不需要对{{ 1}}”。当b意外地比a大时,缺少边界检查可能会导致错误的内存访问。但是,结果可能会更加微妙,并且会导致奇怪的错误,因此正确操作很重要。

您可能希望考虑使用一种更短,更不易出错的方法来实现此顺序:

b

在元组上使用return std::tie(lhs.z, lhs.y, lhs.x) < std::tie(rhs.z, rhs.y, rhs.x); operator<为您提供)automatically (and correctly!) performs the lexicographic breakdown for you

the cppreference page for std::tie上实际上有一个很好的例子,表明这是很常见的事情。