c++ - std::sort() 中的程序有时会崩溃,无法重现

标签 c++ vector stl crash

描述:

我的程序有时会在 std::sort() 中崩溃,我写了一个最小的程序来重现这种情况,但一切都很好。这是最小的例子:

typedef struct st {
    int it;
    char ch;
    char charr[100];
    vector<string *> *vs;
} st;

bool function(st *&s1, st *&s2) {
    static int i = 1;
    cout<<i<<" "<<&s1<<" "<<&s2<<endl;
    ++i;
    return s1->it > s2->it;
}

int main(int argc, char **argv) {
    vector<st *> ar;
    for (int i = 0; i < 100; ++i) {
        st *s = new st;
        s->it = urandom32();
        ar.push_back(s);
    }

    ar.clear();

    for (int i = 0; i < 100; ++i) {
        st *s = new st;
        s->it = urandom32();
        ar.push_back(s);
    }

    sort(ar.begin(), ar.end(), function);

    return 0;
}

这是 GDB 堆栈信息:

  • 0 0x00007f24244d9602 in article_cmp (cand_article_1=0x7f23fd297010, cand_article_2=0x4015) at src/recom_frame_worker.h:47
  • 1 0x00007f24244fc41b in std::__unguarded_partition<__gnu_cxx::__normal_iterator > >, cand_article*, bool ()(cand_article, cand_article*)> (__first=, __last=, __pivot=@0x7f230412b350: 0x7f23fd297010, __comp=0x7f24244d95e1 ) at /usr/include/c++/4.8.3/bits/stl_algo.h:2266
  • 2 0x00007f24244f829c in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator > >, bool ()(cand_article, cand_article*)> (__first=, __last=, __comp=0x7f24244d95e1 ) at /usr/include/c++/4.8.3/bits/stl_algo.h:2296
  • 3 0x00007f24244f1d88 in std::__introsort_loop<__gnu_cxx::__normal_iterator > >, long, bool ()(cand_article, cand_article*)> (__first=, __last=, __depth_limit=18, __comp=0x7f24244d95e1 ) at /usr/include/c++/4.8.3/bits/stl_algo.h:2337
  • 4 0x00007f24244ed6e5 in std::sort<__gnu_cxx::__normal_iterator > >, bool ()(cand_article, cand_article*)> ( __first=, __last=, __comp=0x7f24244d95e1 ) at /usr/include/c++/4.8.3/bits/stl_algo.h:5489

article_cmpsort(article_result->begin(), article_result->end(), article_cmp); 中调用article_result 是 vector<cand_article*> * . cand_article是一个结构。
这是 article_cmp 的定义:

bool article_cmp(cand_article* cand_article_1, cand_article* cand_article_2) {
    return cand_article_1 -> display_time >= cand_article_2 -> display_time;
}

这是发生崩溃的一段代码:

 article_result->clear();
 for(vec_iter = _channel_data -> begin(); vec_iter != _channel_data -> end(); vec_iter++) {
     cand_article* cand = to_cand_group(*vec_iter);
     if(cand == NULL) continue;
     // refresh open loadmore
     if(m_request.req_type == 1) {
         if(cand -> display_time > m_request.start){
             article_result->push_back(cand);
         }
     }else if(m_request.req_type == 2){
         if(cand -> display_time < m_request.end){
             article_result->push_back(cand);
         }
     }else{
         article_result->push_back(cand);
     }
 }

 sort(article_result->begin(), article_result->end(), article_cmp);

问题:

我不知道如何处理这种coredump , 导致 0x4015是内核空间地址?关于如何修复此类错误的任何建议?抱歉,我无法用最小程序重现这种情况。这发生在 single thread ,所以你不需要考虑 multi-thread情况。

最佳答案

规则是“如果 std::sort 崩溃,你有一个无效的比较函数”。你的比较函数是:

bool article_cmp(cand_article* lhs, cand_article* rhs) {
    return lhs -> display_time >= rhs -> display_time;
}

这不是严格的弱排序。特别是,如果显示时间相等,它会返回 true,这意味着如果您交换参数,它仍然会返回 true ...这是不允许的。你需要:

bool article_cmp(cand_article* lhs, cand_article* rhs) {
    return lhs -> display_time > rhs -> display_time;
}

您的简化示例起作用的原因(祝贺您至少尝试 进行了简化)是您简化了比较函数,因此它是有效的。如果 return 语句是 return s1->it >= s2->it;,并且您使用了较小范围的值,它也可能会崩溃。

顺便说一句,您的示例结构的更自然的 C++ 声明如下所示:

struct st {                       // No need for that typedef in C++
    int it;
    char ch;
    std::string charr;            // ... or *possibly* std::array<char,100>.
    std::vector<std::string> vs;  // Strings and vectors best held by value
};

另请注意,我实际上使用了 std:: 前缀。

关于c++ - std::sort() 中的程序有时会崩溃,无法重现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40483971/

相关文章:

java - 使用 JNI 从 Android 调用预构建的 C++ 共享库

c++ - 在 C++ 中为 map 自动生成键

c++ - 使用多个 std::arrays 初始化 2D std::array

c++ - 从 vector 中删除时 vector 迭代器不兼容

c++ - 为 vector<vector<>> 分配内存的捷径

C++ 在循环中删除列表中的对象

c++ - 如何获取当前目录并将其分配给Linux中的变量

c++ - 将 vector 作为参数传递并使用它,为什么会崩溃?

c++ - 编译时出现 make_unique 错误

c++ - 这是 std::quote 错误的行为吗?