【问题标题】:Erratic behavior of GCC's std::sort with lambdasGCC 的 std::sort 与 lambda 的不稳定行为
【发布时间】:2018-03-22 02:19:11
【问题描述】:

以下代码在使用 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;
}

【问题讨论】:

  • 您应该知道,如果您想要的只是词汇比较,那么std::pair 已经在您无需干预的情况下完成了这项工作。
  • @StoryTeller 感谢您的提示。但现在真正困扰我的是分段错误的根源!
  • 来源在您的比较中没有引起适当的顺序关系。由于它,代码具有未定义的行为。
  • 你的比较需要实现一个strict weak ordering - 你的没有这样做。

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


【解决方案1】:

尝试改变

(p1.second <= p2.second)

(p1.second < p2.second)

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

如果你的测试是

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

p1 等于p2 时,您也会获得true

p1 等于p2 时返回true 的比较器...如果我没记错的话,行为是未定义的,因此“不稳定行为”(以及分段错误)是绝对可以理解的.

【讨论】:

    【解决方案2】:

    这里的问题是您的 lambda 不符合 Compare 的标准要求,这需要 strict 弱排序:

    • strict 意味着对于序列中的每个 x!comp(x, x) 必须是 true,而您的自定义比较器 (lambda) 则不是这种情况,因为对于您的每个 xcomp(x, x) == true案例 (x.first == x.first &amp;&amp; x.second &lt;= x.second)。

    您应该将p1.second &lt;= p2.second 更改为p1.second &lt; p2.second,或使用std::pair 的标准比较运算符:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2010-10-11
        • 1970-01-01
        • 2012-04-21
        • 2015-09-11
        • 1970-01-01
        • 2019-11-07
        • 2011-06-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多