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;
}
答
尝试改变
(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
。
有返回true
当p1
等于p2
......如果我没看错的行为是不确定的比较等等的“错误行为”(和分段错误也)是完全可以理解的。
答
这里的问题是,你的拉姆达不符合标准要求Compare
,这需要一个严格弱排序:
-
严格意味着
!comp(x, x)
必须true
为每x
在(x.first == x.first && x.second <= x.second
)中每x
comp(x, x) == true
自定义比较器(lambda)的情况并非如此。
你应该要么改变p1.second <= p2.second
到p1.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>;
}
你应该知道,如果你想要的只是一个词法对比,那么'std :: pair'已经做到了,不需要你的干预。 – StoryTeller
@StoryTeller感谢您的提示。但是现在真正困扰我的是分段故障的来源! –
来源在你的比较中,不会产生正确的顺序关系。该代码具有未定义的行为。 – StoryTeller