c++ - 通过引用传递 vector 然后调用清除

标签 c++ multithreading vector pass-by-reference ownership

我很好奇在通过引用传递后清除 client.cpp 中的 data_received vector 时是否一直在处理未定义的行为?我从来没有遇到过无效数据的问题,但我可以看到这可能是一个问题潜伏的地方。 vector 通过引用一直传递到最终队列 - 与此同时,只有在 queue_event.notify_all() 触发后,另一个线程才会以自己的速率出列。

如果这是一个问题,我认为解决方案可能是在阻塞 client->receive 调用之后清除。想法?

blocking_queue.h

template <typename T>
class BlockingQueue {
    ...
    std::queue<T> queue;
    ...
};

blocking_queue.cpp

template <class T>
void BlockingQueue<T>::enqueue(T const &item)
{
    std::unique_lock<std::mutex> lk (queue_lock);
    queue.push(item);
    lk.unlock();
    queue_event.notify_all(); 
}

template <class T>
T BlockingQueue<T>::dequeue()
{
    std::unique_lock<std::mutex> lk (queue_lock);
    if(queue_event.wait_for(lk, std::chrono::milliseconds(dequeue_timeout))  == std::cv_status::no_timeout)
    {
        T rval = queue.front();
        queue.pop();
        return rval;
    }
    else
    {
        throw std::runtime_error("dequeue timeout");
    }
}

客户端.cpp

void Client::read_from_server()
{
    std::vector<uint8_t> data_received;

    while(run)
    {
        if (client->is_connected())
        {   
            uint8_t buf[MAX_SERVER_BUFFER_SIZE];
            int returned;

            memset(buf, 0, MAX_SERVER_BUFFER_SIZE);
            returned = client->receive(client->get_socket_descriptor(), buf, MAX_SERVER_BUFFER_SIZE);
            // should probably move data_received.clear() to here!!
            if (returned > 0)
            {
                for (int i = 0; i < returned; i++)
                {
                    data_received.push_back(buf[i]);
                }

                if (incoming_queue)
                {
                    incoming_queue->enqueue(data_received);
                }

                data_received.clear();
            }
            else
            {
                client->set_connected(false);
            }
        }    
    }
}

最佳答案

由于 data_received.clear();,我没有看到任何潜在的 UB因为std::queue<T> queue; incoming_queue->enqueue(data_received); 时将保留传递的项目( vector )的拷贝被称为。

如果对队列的访问同步良好(看起来确实如此),那么代码应该是安全的。

关于c++ - 通过引用传递 vector 然后调用清除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44732385/

相关文章:

c# - Monitor.Enter 与 Monitor.Wait

c++ - 使用自定义分配器修改增长策略

c++ - 从 std::shared_ptr<void> 初始化 std::shared_ptr<T>

c++ - 在构建时将对象存储在 vector 中

c++ - DirectX11 获取设备的交换链

c++ - 在网格中的任何位置分布多个零

c++ - vector 列表

c++ - 如何从 boost::thread 中检索线程 ID?

java - 线程池中实际创建线程

c++ - 错误 C2893 函数模板专用化失败 'unknown-type std::invoke(_Callable &&,_Types &&...)'