简体   繁体   English

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

[英]std::sort causes segmentation fault in operator<

I am trying to sort a list ( std::vector ) of 3D integer vectors ( IntVec ).我正在尝试对 3D integer 向量( IntVec )的列表( std::vector )进行排序。 Somehow, std::sort causes a Segmentation Fault in the operator< of IntVec .不知何故, std::sortIntVecoperator<中导致了分段错误。 Here is my code:这是我的代码:

#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());
}

I can provide you the dataset;我可以为您提供数据集; however, I wanted to see at first if I have some big conceptual mistake in my code or some error I do not see.但是,我首先想看看我的代码中是否有一些重大的概念错误或我没有看到的一些错误。 I found that the problem is specific to that dataset.我发现问题是特定于该数据集的。 If I leave out one entry, the Segfault does not occur.如果我遗漏一个条目,则不会发生 Segfault。 I think that is quite weird, since such a mistake should be more obvious and related to memory management.我认为这很奇怪,因为这样的错误应该更明显并且与 memory 管理有关。 Also notice that using integers for x , y and z does not cause any problems.另请注意,对xyz使用整数不会导致任何问题。

Here is a godbolt version of the code.是代码的godbolt版本。

Here is a related SO question .这是一个相关的 SO question However, I think that my code does not have the same flaw that caused this error.但是,我认为我的代码没有导致此错误的相同缺陷。 I think my ordering relation is "strictly <".我认为我的排序关系是“严格<”。

Your operator's logic is broken (does not satisfy strict weak ordering requirement).您的操作员的逻辑被破坏(不满足严格的弱排序要求)。 The final clause needs a lhs.z == rhs.z too.最后一个子句也需要一个lhs.z == rhs.z Otherwise, lhs.z can be > rhs.z but you still get a positive result, leading to an inconsistent ordering.否则, lhs.z可能> rhs.z但您仍然会得到肯定的结果,从而导致排序不一致。

Standard library algorithms put the onus on you to get this right, and breaking the resulting assumptions can easily lead to chaos (read: undefined behaviour) such as segmentation faults.标准库算法让您有责任做到这一点,打破由此产生的假设很容易导致混乱(阅读:未定义的行为),例如分段错误。

Imagine a comment inside the implementation, saying something like "at this point, we know that a is less than b , so we do not need to perform any range/bounds check on b ".想象一下实现中的注释,说“此时,我们知道a小于b ,所以我们不需要对b执行任何范围/边界检查”。 When a is unexpectedly larger than b , that lack of bounds checking may cause bad memory accesses.a意外大于b时,缺少边界检查可能会导致错误的 memory 访问。 The outcome can, however, be far more subtle and cause weird bugs down the line, so it's important to get right.然而,结果可能更加微妙,并导致奇怪的错误,因此正确处理很重要。

You might wish to consider using a shorter, less error-prone method of implementing this ordering:您可能希望考虑使用更短、更不容易出错的方法来实现此排序:

return std::tie(lhs.z, lhs.y, lhs.x) < std::tie(rhs.z, rhs.y, rhs.x);

Using operator< on a tuple (which is what std::tie gives you) automatically (and correctly!) performs the lexicographic breakdown for you .在元组上使用operator< (这是std::tie给你的)自动(并且正确!)为你执行字典分解

There's actually a nice example of this on the cppreference page for std::tie , showing that it's a common thing to do.std::tie的 cppreference 页面上实际上有一个很好的例子,表明这是很常见的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM