GCC&#s; std :: sort与lambdas的不稳定行为

时间:2017-10-10 15:40:57

标签: c++ c++11 gcc lambda stl

使用GCC 6.1.0编译时,以下代码会生成分段错误。奇怪的是,错误是一致的,但不会出现较小的尺寸或略微不同的比较表达式。 你们有什么想法吗?

#include <vector>
#include <algorithm>
#include <iostream>
int main() {
    int n = 1000;   
    std::vector<std::pair<double, double>> vec;
    for(int i = 0; i < n; i++) {
        vec.push_back(std::make_pair<double, double>((7*i)%3, (3*i)%5));
    }
    std::sort(vec.begin(), vec.end(), [](std::pair<double, double> const & p1, std::pair<double, double> const & p2) {return (p1.first < p2.first) || ((p1.first==p2.first)&& (p1.second <= p2.second));}); 
    return 0;
}

3 个答案:

答案 0 :(得分:13)

尝试更改

(p1.second <= p2.second)

(p1.second < p2.second)

我的意思是...... std::sort()需要一个比较器返回true iff(当且仅当)第一个参数(p1严格更低比第二个(p2)。也就是说:当false等于p1时,必须返回p2

如果你的考试是

   (p1.first < p2.first)
|| ((p1.first==p2.first)&& (p1.second <= p2.second))

true等于p1时,您获得p2

true等于p1时,比较器返回p2 ...如果我没有错,则行为未定义,因此出现“不稳定行为”(和分段)故障也是绝对可以理解的。

答案 1 :(得分:11)

此处的问题是您的lambda不符合Compare的标准要求,这需要 严格 弱排序

  • 严格表示对于序列中的每个!comp(x, x)true必须为x,这与您的自定义比较器(lambda)不同,因为{ {1}}适用于您案例中的每个comp(x, x) == truex)。

您应该将x.first == x.first && x.second <= x.second更改为p1.second <= p2.second,或使用p1.second < p2.second的标准比较运算符:

std::pair

答案 2 :(得分:2)

Libstdc ++有debug mode,可以通过定义宏_GLIBCXX_DEBUG来启用。

$ g++-6 b.cc -D_GLIBCXX_DEBUG && ./a.out
/usr/include/c++/6/bits/stl_algo.h:4737:
Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).

Objects involved in the operation:
    instance "functor" @ 0x0x7ffe48ba5a20 {
      type = main::{lambda(std::pair<double, double> const&, std::pair<double, double> const&)#1};
    }
    iterator::value_type "ordered type" {
      type = std::pair<double, double>;
    }