std :: sort中的错误?

时间:2018-01-26 03:06:03

标签: c++ sorting c++11 vector segmentation-fault

好的,我通常默认假设错误在我的代码中,但我所看到的对我来说实际上没有意义。

我有std::vector<DocumentWidget *>,我希望通过一些相对简单的算法对其进行排序。这就是我所看到的。

代码如下所示:

std::vector<DocumentWidget *> documents = DocumentWidget::allDocuments();

// NOTE(eteran): on my system, I have observed a **consistent** crash
// when documents.size() == 17 while using std::sort.
std::sort(documents.begin(), documents.end(), [](const DocumentWidget *a, const DocumentWidget *b) {

    int rc = (a->filenameSet_ == b->filenameSet_) ? 0 : a->filenameSet_ && !b->filenameSet_ ? 1 : -1;
    if (rc != 0) {
        return rc < 0;
    }
    if(a->filename_ < b->filename_) {
        return true;
    }
    return a->path_ < b->path_;
});

看起来很简单,但是当我在列表中有第17个项目时它会崩溃!排序谓词显然没有以任何方式修改vector,所以我看不出这是一个问题。地址清理器和valgrind在此之前没有显示任何错误。

qSort 不会崩溃,似乎工作正常。没有其他正在运行的线程正在接触这些数据,无论我走得多慢,它都会可靠地发生......所以这不是竞争条件。

当我查看调试器时,a参数似乎是“一个结束”迭代器所指向的位置。但如果std::sort行为Crash,则不应该发生这种情况。

注意 std::vector中有17个项目,我强制调试器显示第18个项目,以说明a似乎来自哪里。

我无法想象std::sort被窃听,但我真的很难找到另一种解释。我在这里错过了一些明显的错误吗?!

2 个答案:

答案 0 :(得分:15)

if(a->filename_ < b->filename_) {
    return true;
}
return a->path_ < b->path_;

这被称为“不是有效的严格弱排序”:

{ "a", "d" } < { "b", "c"}; because "a" < "b"
{ "b", "c" } < { "a", "d"}; because "c" < "d"

修复很简单:不要重新发明轮子:

return std::tie(a->filename_, a->path_) < std::tie(b->filename_, b->path_);

答案 1 :(得分:1)

@ T.C。答案是一个很好的答案,因为这个问题被标记为C ++ 11,但是如果未来的读者正在使用C ++ 03解决方案,那么“规范”#c编写这样一个比较运算符的方法(对于成员m1,m2,...... mn)是

if (a->m1 != b-m1)
    return a->m1 < b->m1;
else if (a->m2 != b->m2)
    return a0>m2 < b->m2;
else ...
else if (a->mn != b->mn)
    return a->mn < b->mn;
else
    return false;

(请参阅here进行讨论,问题具有上述风格,但避免使用操作员!=)。

还有一件事是你使用指针而你的代码不是防弹的。如果ab为NULL,则会发生崩溃。如果你不能避免指针而你想要偏执,那么你需要添加像

这样的支票
if (!a && !b)
    return false;
else if (!a)
    return true;
else if (!b)
    return false;