在set :: insert上的Segfault

时间:2011-06-07 11:21:04

标签: c++ stl segmentation-fault

我在以下行之后遇到了段错误:

this->my_set.insert(my_string);

该集已初始化并包含std :: string。 插入字符串不是指一个dandling指针,它是以null结尾的。 集合中包含的所有其他字符串都不为null,并以'\ 0'结尾。

这是回溯:

#0  0xb7076bdb in std::_Rb_tree_insert_and_rebalance () from /usr/lib/libstdc++.so.6
#1  0xb7480795 in std::_Rb_tree<std::string, std::string, std::_Identity<std::string>, std::less<std::string>, std::allocator<std::string> >::_M_insert_ (
    this=0x97bf918, __x=0x0, __p=0x980aa78, __v=@0xaabfc1c4) at /usr/include/c++/4.3/bits/stl_tree.h:854<br/>
#2  0xb7480b96 in std::_Rb_tree<std::string, std::string, std::_Identity<std::string>, std::less<std::string>, std::allocator<std::string> >::_M_insert_unique (this=0x97bf918, __v=@0xaabfc1c4) at /usr/include/c++/4.3/bits/stl_tree.h:1148
#3  0xb74fab2d in std::set<std::string, std::less<std::string>, std::allocator<std::string> >::insert (this=0x97bf918, __x=@0xaabfc1c4)
    at /usr/include/c++/4.3/bits/stl_set.h:381

有什么想法吗?


修改

更多代码:

set<string> dangerous_messages; //placed in header file

            qpid::client::Message msg;
            msg = (*mylocal_queues)[queue]->get(10*1e9);
            string msgUID = msg.getHeaders().getAsString("UID");
            if(this->dangerous_messages.count(msgUID))
            {
                       warning("(read_local_queue) Duplicate message \""+msgUID+"\" discarded");
           }
           else
           {
                        msg.getHeaders().setString("BID", bid);
                        this->dangerous_messages.insert(msgUID);
            }

使用gdb打印,我没有注意到集合或字符串中的任何损坏。

4 个答案:

答案 0 :(得分:5)

问题也可能位于其他地方。程序中某些其他位置的溢出可能会在您插入集合时导致段错误。插入只是识别错误的时间点,但根本不一定与错误有关。

考虑这个组成的例子:

vector<MyObj*> ptrs;
if/for/while (...)
{
    MyObj o;
    ptrs.push_back(&o);
}  // end of scopre for o
// Your heap is corrupted, but no segfault has to occur right away
...
// Your insertion occurs somewhere later
// No the program segfaults because of the problem you created earlier

答案 1 :(得分:4)

由于您声明代码是多线程而没有锁定,这可能是竞争条件的结果。 (至少一个竞争条件可能会导致完全相同的堆栈跟踪。)

使用正确的锁以确保正确执行。例如,如果您使用的是OpenMP,请将您向我们展示的代码更改为:

#pragma omp critical
{
    if(this->dangerous_messages.count(msgUID))
    {
        warning("(read_local_queue) Duplicate message \""+msgUID+"\" discarded");
    }
    else
    {
        msg.getHeaders().setString("BID", bid);
        this->dangerous_messages.insert(msgUID);
    }
}

但总的来说,如果发生这样的错误,你的代码逻辑基本上是有缺陷的。 在没有干净的跨线程接口的情况下,您不能在线程之间共享状态。使用预定义的跨线程通信结构在线程之间共享状态,或使用只读状态。跨线程写入几乎都不行。

答案 2 :(得分:0)

您的堆可能已损坏,您的字符串或设置实例可能已被破坏。

答案 3 :(得分:0)

狂野猜测:包含my_set的对象已经超出范围/已被销毁。

如果您想要更精确的答案,则必须发布更多代码。