代码之家  ›  专栏  ›  技术社区  ›  achimedzz

为什么std::sort使用这种简单的严格弱排序比较仍然崩溃?[副本]

  •  0
  • achimedzz  · 技术社区  · 1 年前

    这是我的代码:

    #include<vector>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    void test()
    {
        vector<vector<int>> info = {{0,0,999}, {0,1,1000}, {0,2,1001},
                    {0,3,1002}, {0,4,1003}, {0,5,1004},
                    {0,6,1005}, {0,7,1006}, {1,0,1000},
                    {1,1,999}, {1,2,1000}, {1,3,1001},
                    {1,4,1002}, {1,5,1003}, {1,6,1004},
                    {1,7,1005}, {2,0,1001}, {2,1,1000},
                    {2,2,999}, {2,3,1000}, {2,4,1001},
                    {2,5,1002}, {2,6,1003}, {2,7,1004},
                    {3,0,1002}, {3,1,1001}, {3,2,1000},
                    {3,3,999}, {3,4,1000}, {3,5,1001},
                    {3,6,1002}, {3,7,1003}, {4,0,1003},
                    {4,1,1002}, {4,2,1001}, {4,3,1000},
                    {4,4,999}, {4,5,1000}, {4,6,1001},
                    {4,7,1002}, {5,0,1004}, {5,1,1003},
                    {5,2,1002}, {5,3,1001}, {5,4,1000},
                    {5,5,999}, {5,6,1000}, {5,7,1001},
                    {6,0,1005}, {6,1,1004}, {6,2,1003},
                    {6,3,1002}, {6,4,1001}, {6,5,1000},
                    {6,6,999}, {6,7,1000}, {7,0,1006},
                    {7,1,1005}, {7,2,1004}, {7,3,1003},
                    {7,4,1002},{7,5,1001}};  
        auto cmp=[](const auto& a,const auto& b){
          if(a[2]<b[2])return true;
          if(a[0]<b[0])return true;
          return a[1]<b[1];       
     };
    
     sort(begin(info),end(info),cmp);
    
    }
    int main()
    {
      test();
    }
    

    我在Ubuntu 24.04 LTS(Linux 6.8.0-39-general)下使用g++13.2编译构建并运行排序时出现代码崩溃,非常奇怪:

    zzhao@zzhao-System-Version:~$ g++  -std=c++20 z3.cpp
    
    zzhao@zzhao-System-Version:~$ ./a.out
    
    Segmentation fault (core dumped)
    
    2 回复  |  直到 1 年前
        1
  •  1
  •   wohlstad    1 年前

    你的比较器不遵守严格的弱序。

    例如: a={2,0,1},b={1,0,2}

    对于<b(由于第一 if 在比较器中),但对于b<a(由于第二 如果 在里面)。

    由于这不符合比较器的要求 std::sort ,它会导致未定义的行为。

        2
  •  0
  •   Salt    1 年前

    代码崩溃是因为排序的比较函数搞砸了。基本上,它没有遵循std::sort正常工作所需的规则。原来的功能到处都是,有时说一件事更小,有时不是——它超级不一致。

    为了解决这个问题,我不得不重写比较部分。现在它先检查第三个数字,然后检查第一个,然后检查第二个。这样更符合逻辑和一致性。

    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    void test() {
        std::vector<std::vector<int>> info = {{0,0,999}, {0,1,1000}, {0,2,1001},
                    {0,3,1002}, {0,4,1003}, {0,5,1004},
                    {0,6,1005}, {0,7,1006}, {1,0,1000},
                    {1,1,999}, {1,2,1000}, {1,3,1001},
                    {1,4,1002}, {1,5,1003}, {1,6,1004},
                    {1,7,1005}, {2,0,1001}, {2,1,1000},
                    {2,2,999}, {2,3,1000}, {2,4,1001},
                    {2,5,1002}, {2,6,1003}, {2,7,1004},
                    {3,0,1002}, {3,1,1001}, {3,2,1000},
                    {3,3,999}, {3,4,1000}, {3,5,1001},
                    {3,6,1002}, {3,7,1003}, {4,0,1003},
                    {4,1,1002}, {4,2,1001}, {4,3,1000},
                    {4,4,999}, {4,5,1000}, {4,6,1001},
                    {4,7,1002}, {5,0,1004}, {5,1,1003},
                    {5,2,1002}, {5,3,1001}, {5,4,1000},
                    {5,5,999}, {5,6,1000}, {5,7,1001},
                    {6,0,1005}, {6,1,1004}, {6,2,1003},
                    {6,3,1002}, {6,4,1001}, {6,5,1000},
                    {6,6,999}, {6,7,1000}, {7,0,1006},
                    {7,1,1005}, {7,2,1004}, {7,3,1003},
                    {7,4,1002},{7,5,1001}};  
    
        auto cmp = [](const auto& a, const auto& b) {
            if (a[2] != b[2]) return a[2] < b[2];
            if (a[0] != b[0]) return a[0] < b[0];
            return a[1] < b[1];
        };
    
        std::sort(begin(info), end(info), cmp);
    
        for (const auto& v : info) {
            std::cout << v[0] << " " << v[1] << " " << v[2] << std::endl;
        }
    }
    
    int main() {
        test();
        return 0;
    }