【问题标题】:seg fault/undefined behavior in comparator function of std::mapstd::map 的比较器函数中的段错误/未定义行为
【发布时间】:2019-01-09 01:59:24
【问题描述】:

今天这让我很困惑。

我无法理解为什么下面的代码在最终插入 test_map 时会出现段错误。使用 emplace()、insert() 都按预期工作,但使用 [] 运算符失败。我已经阅读了 [] 的相关 C++ 文档,但下面观察到的行为似乎与我所阅读的不符。

我在 GDB 中单步执行并注意到在比较器函数中尝试比较字符串时它失败了。

#include <iostream>
#include <map>
#include <iostream>

class Testkey {
public:
    std::string s1;
    int64_t id;
    Testkey(const char* s1_, int64_t id_): s1(s1_), id(id_) {}

    bool operator<(const Testkey& rhs) const {
        if (s1 < rhs.s1)
            return true;
        if (id < rhs.id)
            return true;
        return false;
    }
};

int main() {
    Testkey i1("69739", 748072524);
    Testkey i2("69728", 52608624);
    Testkey i3("69725", 750212380);
    Testkey i4("68988", 55027788);

    std::map<Testkey, int> test_map;
    test_map[i1] = 1;
    test_map[i2] = 2;
    test_map[i3] = 3;
    std::cout << "hmm.." << std::endl;
    test_map[i4] = 4; // seg faults here in comparator function...
    std::cout << "done" << std::endl;
    return 0;
}

我在这里附上了一个repl https://repl.it/repls/RundownSparklingComment

【问题讨论】:

  • 按照你的逻辑,"(1, 2)

标签: c++ c++11 segmentation-fault undefined-behavior


【解决方案1】:

您的比较功能已损坏。你可能是这个意思:

bool operator<(const Testkey& rhs) const {
    if (s1 < rhs.s1)
        return true;
    if (s1 > rhs.s1)
        return false;
    if (id < rhs.id)
        return true;
    return false;
}

用于std::map 的比较函数必须定义要插入或比较的对象的strict weak ordering,而您的函数没有,因为i3&lt;i2i2&lt;i3 都为真。

【讨论】:

  • 如果我误解了,请原谅我,但是损坏的比较功能会导致段错误/UB吗?最糟糕的是,它不会最终将我的记录插入到错误的地方吗?
  • 这取决于比较功能的破坏程度。如果它这么坏,它根本无法识别任何地方,那么任何事情都可能发生。尝试同时将i3 放在i2 之前和i2 之前放在i3 之前不会提供任何特别错误的放置位置。 (在我的 STL 中,插入检查以确保它不会运行结束,运行不处理运行结束情况的代码,但无论如何都会运行结束并访问越界。)
  • @shinjin -- 仅供参考,对于 Visual C++ 编译器,损坏的比较运算符将导致调试运行时出现assert 失败。所以不,更糟糕的不仅仅是把记录放在错误的地方。
猜你喜欢
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 2020-10-02
  • 2020-08-09
相关资源
最近更新 更多