我把一个异步的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;
}
}
};