提升asio"矢量迭代器不可解除引用"

时间:2016-06-16 18:09:33

标签: c++ boost-asio shared-ptr

我把一个异步的UDP客户端(下面的代码)放在一起,它抛出错误"矢量迭代器而不是可解引用的"运行约4秒后。在boost asio上下文中似乎没有关于此错误的确切原因的信息很少,但似乎可能是由于缓冲区超出范围。

我使用的是共享指针,但我无法看到任何可能超出范围的内容。

调用堆栈:

std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 15   C++
std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > >::operator*() Line 72 C++
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > >::operator*() Line 325  C++
boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > >::operator()() Line 532   C++
[External Code] 
boost::asio::detail::buffer_cast_helper(const boost::asio::mutable_buffer & b) Line 146 C++
boost::asio::buffer_cast<void const *>(const boost::asio::mutable_buffer & b) Line 427  C++
boost::asio::detail::buffer_sequence_adapter<boost::asio::const_buffer,boost::asio::mutable_buffers_1>::validate(const boost::asio::mutable_buffers_1 & buffer_sequence) Line 207   C++
boost::asio::detail::win_iocp_socket_send_op<boost::asio::mutable_buffers_1,boost::_bi::bind_t<void,boost::_mfi::mf2<void,client_t,boost::system::error_code const &,unsigned int>,boost::_bi::list3<boost::_bi::value<client_t *>,boost::arg<1>,boost::arg<2> > > >::do_complete(boost::asio::detail::win_iocp_io_service * owner, boost::asio::detail::win_iocp_operation * base, const boost::system::error_code & result_ec, unsigned int bytes_transferred) Line 70    C++
boost::asio::detail::win_iocp_operation::complete(boost::asio::detail::win_iocp_io_service & owner, const boost::system::error_code & ec, unsigned int bytes_transferred) Line 46   C++
boost::asio::detail::win_iocp_io_service::do_one(bool block, boost::system::error_code & ec) Line 406   C++
boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec) Line 164  C++
boost::asio::io_service::run() Line 59  C++
boost::_mfi::mf0<unsigned int,boost::asio::io_service>::operator()(boost::asio::io_service * p) Line 50 C++
boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> >::operator()<unsigned int,boost::_mfi::mf0<unsigned int,boost::asio::io_service>,boost::_bi::list0>(boost::_bi::type<unsigned int> __formal, boost::_mfi::mf0<unsigned int,boost::asio::io_service> & f, boost::_bi::list0 & a, long __formal) Line 250 C++
boost::_bi::bind_t<unsigned int,boost::_mfi::mf0<unsigned int,boost::asio::io_service>,boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> > >::operator()() Line 1223   C++
boost::detail::thread_data<boost::_bi::bind_t<unsigned int,boost::_mfi::mf0<unsigned int,boost::asio::io_service>,boost::_bi::list1<boost::_bi::value<boost::asio::io_service *> > > >::run() Line 117  C++
boost::`anonymous namespace'::thread_start_function(void * param) Line 303  C++
[External Code] 

它似乎发生在&#39; do_send&#39;功能调用&#39; async_send_to&#39;但共享指针存储在已发送的内容中,因此我不知道如何删除它?

上课:

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <boost/atomic.hpp>

#include <string>
#include <vector>

namespace asio = boost::asio;
namespace posix_time = boost::posix_time;
namespace lockfree = boost::lockfree;

typedef std::vector<uint8_t> msg_t;
typedef boost::shared_ptr<msg_t> spmsg_t;
typedef boost::shared_ptr<asio::io_service::work> pwork_t;
typedef lockfree::spsc_queue<spmsg_t> msg_queue_t;

struct client_t {
    asio::io_service &_svc;
    asio::ip::udp::socket _socket;
    asio::ip::udp::endpoint _ep;
    boost::atomic<bool> _connected;
    boost::atomic<bool> _closing;
    boost::thread _worker;
    pwork_t _work;
    msg_queue_t _send_queue;
    msg_queue_t _recv_queue;
    boost::condition_variable m_cond;
    boost::mutex m_Mutex;

    client_t(asio::io_service &svc_) :_svc(svc_), _send_queue(1024), _recv_queue(1024), _socket(svc_, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)){}

    void init(const std::string ip_, const std::string port_) {
        _closing = false;
        sending = false;
        _connected = true;

        boost::asio::ip::udp::resolver resolver(_svc);
        _ep = *resolver.resolve({ boost::asio::ip::udp::v4(), ip_, port_ });

        _work = pwork_t(new asio::io_service::work(_svc));
        _worker.swap(boost::move(boost::thread(boost::bind(&asio::io_service::run, &_svc))));

        _svc.post(boost::bind(&client_t::do_recv, this));
    }

    void destroy() {
        _work.reset();
        _worker.join();

        _send_queue.reset();
        _recv_queue.reset();
    }

    bool is_connected() {
        return !_closing && _connected;
    }

    void disconnect() {
        _closing = true;
    }

    boost::atomic<bool> sending;
    spmsg_t sended;
    void do_send() {
        if (_send_queue.pop(sended)) {
            _socket.async_send_to(asio::buffer(*sended), _ep, boost::bind(&client_t::handle_sended, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
        }
        else {
            sending.store(false);
            if (_closing) {
                _socket.shutdown(asio::ip::tcp::socket::shutdown_both);
                _socket.close();

                _send_queue.reset();
                _recv_queue.reset();

                _connected = false;
                _closing = false;
            }       
        }

    }
    void handle_sended(const boost::system::error_code &ec_, std::size_t bytes_transferred) {
        if (ec_) {
            sending.store(false);
            printf("%s\n", ec_.message().c_str());
            return;
        }

        do_send();
    }


    spmsg_t recv_msg;
    void do_recv() {
        recv_msg = boost::make_shared<msg_t>(2048);
        _socket.async_receive_from(asio::buffer(recv_msg->data() + 4, 2044), _ep, boost::bind(&client_t::handle_recv, this, asio::placeholders::error, asio::placeholders::bytes_transferred));
    }
    void handle_recv(const boost::system::error_code &ec_, std::size_t bytes_transferred_) {

        if (ec_) {
            printf("%s\n",ec_.message().c_str());
            return;
        }
        *(uint32_t*)recv_msg->data() = bytes_transferred_;
        if (_recv_queue.push(recv_msg)) {

            m_cond.notify_one();

            do_recv();
        }
        else {
            disconnect();
        }
    }

    //spmsg_t get_sended(uint32_t len_) { return spmsg_t(new msg_t(len_ + 4)); }

    bool send(unsigned char* msg, int msgSize) {
        if (!is_connected())
            return false;

        spmsg_t msg_ = spmsg_t(new msg_t(msgSize));
        memcpy(&msg_->data()[0], msg, msgSize);

        if (!_send_queue.push(msg_))
            return false;

        //send_messages();

        return true;
    }
    bool send_messages() {
        if (!is_connected())
            return false;
        static bool f = false;
        if (!sending.compare_exchange_strong(f, true))
            return false;

        _svc.post(boost::bind(&client_t::do_send, this));
    }


    spmsg_t recv() {
        if (!is_connected())
            return NULL;

        spmsg_t recved;
        if (_recv_queue.pop(recved))
            return recved;
        else{
            boost::mutex::scoped_lock lock(m_Mutex);
            if (m_cond.timed_wait(lock, boost::posix_time::milliseconds(5000)))
            {
                _recv_queue.pop(recved);
                return recved;
            }
            else
                return NULL;
        }

    }
};

0 个答案:

没有答案