由于互斥锁,C ++向量擦除迭代器超出范围

时间:2014-02-09 19:04:59

标签: c++ vector iterator mutex erase

所以,有一个字符串向量。由于它是cl_mgr类的静态成员,因此它充当全局变量。

std::vector<std::string> cl_mgr::to_send_queue;

但是,我不会在我的代码中直接访问此向量。要为其添加字符串,我调用以下函数:

void cl_mgr::sendmsg(std::string msg)
{
    std::mutex mtx;

    mtx.lock();
    if ( connected )
    {
        cl_mgr::to_send_queue.push_back(msg + '\r');
    }
    mtx.unlock();
}

这是出错的地方:线路 cl_mgr :: to_send_queue.erase(cl_mgr :: to_send_queue.begin()); 有时会使迭代器超出范围。 这应该只在vector为空时发生,但我已经在条件状态下检查了这一点。

接下来我添加了sizes数组,用to_send_queue.size()填充它,有时发现它返回零!通常所有数组都包含1个,但有时像size [9500]这样的元素是0。

什么是错的以及如何解决这个问题?

std::mutex mtx;
mtx.lock();
while ( !cl_mgr::to_send_queue.empty() )
{
    string tosend = cl_mgr::to_send_queue[0];

    int sizes[10000];
    sizes[0]=0;
    for (int i = 1; i < 10000; ++i)
    {
        sizes[i] = cl_mgr::to_send_queue.size();
        if ( sizes[i] < sizes[i-1] )
        {
            int breakpoint = 0; //should never be hit but it does !
        }
    }

    cl_mgr::to_send_queue.erase(cl_mgr::to_send_queue.begin()); //CRASH HERE

    send(hSocket, tosend.c_str(), tosend.length(), 0 );


    Sleep(5);
}
mtx.unlock();

1 个答案:

答案 0 :(得分:3)

std::mutex是方法的本地。这意味着此方法的每次调用都有自己的互斥锁,并且不会保护任何内容。

要解决此问题,您必须将互斥锁移动到与向量to_send_queue相同的范围并使用std::lock_guard。在网站上,有一个例子如何使用这个

int g_i = 0;
std::mutex g_i_mutex;  // protects g_i

void safe_increment()
{
    std::lock_guard<std::mutex> lock(g_i_mutex);
    ++g_i;

    std::cout << std::this_thread::get_id() << ": " << g_i << '\n';

    // g_i_mutex is automatically released when lock
    // goes out of scope
}