std :: sort()中的程序崩溃有时无法重现

时间:2016-11-08 10:02:12

标签: 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堆栈信息:

  
      article_cmp中的
  • 0 0x00007f24244d9602(cand_article_1 = 0x7f23fd297010, cand_article_2 = 0x4015 )   在src / recom_frame_worker.h:47
  •   
  • 1 0x00007f24244fc41b in std :: __ unguarded_pa​​rtition&lt; __ gnu_cxx :: __ normal_iterator&gt; &gt;中   cand_article *,bool()(cand_article ,cand_article *)&gt; (__first =,   __last =,__ pivot = @ 0x7f230412b350:0x7f23fd297010,   __comp = 0x7f24244d95e1)   在/ usr / include / c ++ / 4.8.3 / bits / stl_algo.h:2266
  •   
  • 2 0x00007f24244f829c in std :: __ unguarded_pa​​rtition_pivot&lt; __ gnu_cxx :: __ normal_iterator&gt; &gt;,布尔   ()(cand_article ,cand_article *)&gt; (__ first =,__last =,   __comp = 0x7f24244d95e1)   在/ usr / include / c ++ / 4.8.3 / bits / stl_algo.h:2296
  •   
  • 3 0x00007f24244f1d88 in std :: __ introsort_loop&lt; __ gnu_cxx :: __ normal_iterator&gt; &gt;,长,   bool()(cand_article ,cand_article *)&gt; (__ first =,__last =,   __depth_limit = 18,   __comp = 0x7f24244d95e1)   在/ usr / include / c ++ / 4.8.3 / bits / stl_algo.h:2337
  •   
  • 4 0x00007f24244ed6e5 in std :: sort&lt; __ gnu_cxx :: __ normal_iterator&gt; &gt;,布尔   ()(cand_article ,cand_article *)&gt; (   __first =,__last =,__ comp = 0x7f24244d95e1)   在/ usr / include / c ++ / 4.8.3 / bits / stl_algo.h:5489
  •   
article_cmp中调用

sort(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情况。

2 个答案:

答案 0 :(得分:4)

规则是&#34;如果std::sort崩溃,则您的比较功能无效&#34;。您的比较功能是:

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::前缀。

答案 1 :(得分:0)

  1. 您的最小程序正在使内存泄漏。因为它只是从列表中删除所有项目但没有释放它们使用的内存。如果您的项目足够大,您的程序可能会在吃完所有内存后崩溃。这就是为什么你的最小程序仍然可以,因为那里的项目非常小。

  2. 我会将您的计划更改为:

    typedef struct st {     在它;     char ch;     char charr [100];     矢量* vs; } st;

    bool函数(st *&amp; s1,st *&amp; s2){     static int i = 1;     cout&lt; it&gt; S2-&gt;其; }

    int main(int argc,char ** argv){     矢量ar;     for(int i = 0; i&lt; 100; ++ i){         st * s = new st;         s-&gt; it = urandom32();         ar.push_back(一个或多个);     }

    首先释放所有使用我的ar项目的内存

    for(vector :: iterator it = ar.begin(); it!= ar.end(); ++ it)     删除*它;

    ar.clear();

    .columns {
        column-count: 2;
        column-gap: 12px;
    }
    .columns p {
        /* don't break paragraphs */
        break-inside: avoid; 
        /* Use padding instead of margin to avoid weird space at top of the second column.*/
       margin: 0;
       padding-bottom: 14px;
    }
    

    }