GCC std :: sort与lambdas的错误行为

问题描述:

以下代码在使用GCC 6.1.0进行编译时会生成分段错误。奇怪的是,错误是一致的,但不会发生较小的尺寸或略有不同的比较表达式。 你们有什么想法,为什么?GCC std :: sort与lambdas的错误行为

#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; 
} 
+0

你应该知道,如果你想要的只是一个词法对比,那么'std :: pair'已经做到了,不需要你的干预。 – StoryTeller

+0

@StoryTeller感谢您的提示。但是现在真正困扰我的是分段故障的来源! –

+5

来源在你的比较中,不会产生正确的顺序关系。该代码具有未定义的行为。 – StoryTeller

尝试改变

(p1.second <= p2.second) 

(p1.second < p2.second) 

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

如果测试是

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

你获得true也当p1等于p2

有返回truep1等于p2 ......如果我没看错的行为是不确定的比较等等的“错误行为”(和分段错误也)是完全可以理解的。

这里的问题是,你的拉姆达不符合标准要求Compare,这需要一个严格弱排序

  • 严格意味着!comp(x, x)必须true为每x在(x.first == x.first && x.second <= x.second)中每xcomp(x, x) == true自定义比较器(lambda)的情况并非如此。

你应该要么改变p1.second <= p2.secondp1.second < p2.second,或使用标准的比较运算符std::pair

std::sort(vec.begin(), vec.end()); 

的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>; 
    }