簡體   English   中英

std::sort 的 std::vector 產生非法元素

[英]std::sort of std::vector produces illegal elements

我有一個應用程序,其中 std::sort 有時會導致核心轉儲。 我能夠將問題隔離到以下 MWE:

#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>

class DF {
  public:
    DF() = default;

    std::vector<int> row_mapping;
    std::vector<int> idx = {0, 1};
    std::vector<std::vector<int>> vals = {
        {0,  0,  0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,
         4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,
         8,  8,  8,  8,  9,  9,  9,  9,  10, 10, 10, 10, 11, 11, 11, 11,
         12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14},

        {2015, 2016, 2017, 2021, 2015, 2016, 2017, 2021, 2015, 2016, 2017,
         2021, 2015, 2016, 2017, 2021, 2015, 2016, 2017, 2021, 2015, 2016,
         2017, 2021, 2015, 2016, 2017, 2021, 2015, 2016, 2017, 2021, 2015,
         2016, 2017, 2021, 2015, 2016, 2017, 2021, 2015, 2016, 2017, 2021,
         2015, 2016, 2017, 2021, 2015, 2016, 2017, 2021, 2014, 2015, 2016,
         2017, 2021, 2015, 2016, 2017, 2021}};

    void sort(void) {
        int n = vals[0].size();
        std::cerr << "n = " << n << std::endl;

        row_mapping.resize(n);
        std::iota(begin(row_mapping), end(row_mapping), 0);

        std::cerr << "row map:";
        for (auto v : row_mapping) std::cerr << " " << v;
        std::cerr << std::endl;

        std::sort(
            begin(row_mapping), end(row_mapping), [&](int i1, int i2) -> bool {
                std::cerr << "cmp " << i1 << " " << i2 << std::endl;
                for (auto gi : idx) {
                    if (vals[gi][i1] < vals[gi][i2]) return true;
                }
                return false;
            });
    }
};

int main() {
    DF df;
    df.sort();
}

在使用g++ -std=c++17 mwe.cpp並運行它后,我得到:

(輸出縮寫)

n = 61
row map: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
cmp 1 30
cmp 30 60
(...)
cmp 52 257
(...)
cmp 59 55
cmp 60 56
double free or corruption (out)
Aborted (core dumped)

這很奇怪,因為我對包含值 0 到 60(包括)的向量進行排序,這些值是更復雜數據結構的索引。 但是比較 lambda 被調用,值為 257。

我想這一定是因為超出了某些數組邊界,或者因為對不再存在的數據的引用。 但是我在代碼中看不到問題!

確實這就是問題所在。

使用以下更正的 lamda,一切正常:

 std::sort(
            begin(row_mapping), end(row_mapping), [&](int i1, int i2) -> bool {
                std::cerr << "cmp " << i1 << " " << i2 << std::endl;
                for (auto gi : idx) {
                    if (vals[gi][i1] < vals[gi][i2]) return true;
                    if (vals[gi][i1] > vals[gi][i2]) return false;
                }
                return false;
            });

您的比較操作沒有定義嚴格的弱排序。

        for (int i1 = 0; i1 < vals[0].size(); ++i1)
        {
            for (int i2 = 1; i2 < vals[0].size(); ++i2)
            {
                if (!(cmp(i1, i2) ^ cmp(i2, i1)))
                {
                    std::cerr << "incongruent comparison between " << i1 << " and " << i2 << '\n';
                    assert(0);
                }
            }
        }

Output:

incongruent comparison between 0 and 52

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM