C ++ boost :: asio连接weak_ptr错误

时间:2019-02-26 05:03:40

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

我在C ++ TCP Server中有问题(使用boost asio)。
在普通客户端中,许多客户端连接到服务器是正常的。 但是,如果每个客户端以每秒10次的速度连接和断开服务器,则服务器会花费一些时间。

(1)创建这样的服务器:

void ClientConnection::start()
{
  socket_.async_read_some(boost::asio::buffer(buffer_),
      strand_.wrap(
        boost::bind(&connection::handle_read, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred)));
}

void ClientConnection::closeSocket() {
    mStrand.post(boost::bind(&ClientConnection::innerCloseSocket, this->shared_from_this()));
}

void ClientConnection::innerCloseSocket() {
    boost::system::error_code error;
    mSocket.close(error);
    LOG_INFO("Close client[" << mClientId << "] socket connection");  //line:216
}

ClientConnection::~ClientConnection() {
}

(2)hand_read像这样:

void ClientConnection::handle_read(const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
  if (!e)
  {
      //read data and use it
  }
  else { //error occurs 
      closeSocket();

      boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
      cmd->setClient(this->weak_from_this());  //here set this connection weak_ptr

      putCmd(cmd);  //do something in other thread.
  }
}

(3)handle_write像这样:

void ClientConnection::handle_write(const boost::system::error_code& e)
{
  if (!e)
  {
    //send data
  }
  else { //error occurs 
      closeSocket();

      boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
      cmd->setClient(this->weak_from_this());  //here set this connection weak_ptr

      putCmd(cmd);  //do something in other thread.
  }  
}

核心

但是,当许多客户端连接到服务器时,服务器是核心。核心就像一个连接被破坏了两次,内存是错误的。

bt这样:

#0  0x00007f6e3aa561f7 in raise () from /lib64/libc.so.6
#1  0x00007f6e3aa578e8 in abort () from /lib64/libc.so.6
#2  0x00007f6e3b35c9d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
#3  0x00007f6e3b35a946 in ?? () from /lib64/libstdc++.so.6
#4  0x00007f6e3b35a973 in std::terminate() () from /lib64/libstdc++.so.6
#5  0x00007f6e3b35ab93 in __cxa_throw () from /lib64/libstdc++.so.6
#6  0x00007f6e3b35b12d in operator new(unsigned long) () from /lib64/libstdc++.so.6
#7  0x00007f6e3b3b9c79 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /lib64/libstdc++.so.6
#8  0x00007f6e3b3ba8bb in std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) () from /lib64/libstdc++.so.6
#9  0x00007f6e3b3ba964 in std::string::reserve(unsigned long) () from /lib64/libstdc++.so.6
#10 0x00007f6e3b3baa28 in std::string::append(std::string const&) () from /lib64/libstdc++.so.6
#11 0x00007f6e3be5c4c8 in log4cxx::helpers::CharMessageBuffer::operator<< (this=0x7f6e20ff8750, msg=...) at messagebuffer.cpp:31
#12 0x00000000008a3a05 in ClientConnection::internalCloseSocket (this=0x7f6e046fefd0) at src/business/ClientConnection.cpp:216
#13 0x00000000008b620a in boost::_mfi::mf0<void, ClientConnection>::call<boost::shared_ptr<ClientConnection> > (this=0x7f6e20ff89c0, u=...)
    at externals/boost/include/boost/bind/mem_fn_template.hpp:40
#14 0x00000000008b5c79 in boost::_mfi::mf0<void, ClientConnection>::operator()<boost::shared_ptr<ClientConnection> > (this=0x7f6e20ff89c0, u=...)
    at externals/boost/include/boost/bind/mem_fn_template.hpp:55
#15 0x00000000008b5416 in boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > >::operator()<boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list0> (
    this=0x7f6e20ff89d0, f=..., a=...) at externals/boost/include/boost/bind/bind.hpp:259
#16 0x00000000008b4997 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > >::operator() (this=0x7f6e20ff89c0) at externals/boost/include/boost/bind/bind.hpp:1294
#17 0x00000000008b3667 in boost::asio::asio_handler_invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > > (function=...) at externals/boost/include/boost/asio/handler_invoke_hook.hpp:69
#18 0x00000000008b235a in boost_asio_handler_invoke_helpers::invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > >, boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > > (
    function=..., context=...) at externals/boost/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#19 0x00000000008b0ee3 in boost::asio::detail::completion_handler<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > >::do_complete (owner=0x1a5a5c0, base=0x7f6e28018f30) at externals/boost/include/boost/asio/detail/completion_handler.hpp:68
#20 0x00000000007c3ef4 in boost::asio::detail::task_io_service_operation::complete (this=0x7f6e28018f30, owner=..., ec=..., bytes_transferred=0)
    at externals/boost/include/boost/asio/detail/task_io_service_operation.hpp:38
#21 0x00000000007c7937 in boost::asio::detail::strand_service::do_complete (owner=0x1a5a5c0, base=0x7f6df001ab40, ec=...) at externals/boost/include/boost/asio/detail/impl/strand_service.ipp:167
#22 0x00000000007c3ef4 in boost::asio::detail::task_io_service_operation::complete (this=0x7f6df001ab40, owner=..., ec=..., bytes_transferred=0)
    at externals/boost/include/boost/asio/detail/task_io_service_operation.hpp:38
#23 0x00000000007c5dde in boost::asio::detail::task_io_service::do_run_one (this=0x1a5a5c0, lock=..., this_thread=..., ec=...) at externals/boost/include/boost/asio/detail/impl/task_io_service.ipp:372
#24 0x00000000007c5845 in boost::asio::detail::task_io_service::run (this=0x1a5a5c0, ec=...) at externals/boost/include/boost/asio/detail/impl/task_io_service.ipp:149
#25 0x00000000007c60cf in boost::asio::io_service::run (this=0x1a54b10) at externals/boost/include/boost/asio/impl/io_service.ipp:59
#26 0x00000000008c27b6 in ProcessModule::threadRun (this=0x1a54b10) at src/business/ProcessModule.cpp:149
#27 0x00000000008c82e7 in boost::_mfi::mf0<void, ProcessModule>::operator() (this=0x1b0aee8, p=0x1a54b10) at externals/boost/include/boost/bind/mem_fn_template.hpp:49
#28 0x00000000008c824a in boost::_bi::list1<boost::_bi::value<ProcessModule*> >::operator()<boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list0> (this=0x1b0aef8, 
    f=..., a=...) at externals/boost/include/boost/bind/bind.hpp:259
#29 0x00000000008c81f9 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list1<boost::_bi::value<ProcessModule*> > >::operator() (
    this=0x1b0aee8) at externals/boost/include/boost/bind/bind.hpp:1294
#30 0x00000000008c811a in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list1<boost::_bi::value<ProcessModule*> > > >::run (this=0x1b0ad30) at externals/boost/include/boost/thread/detail/thread.hpp:116

(gdb) p *this
$1 = {<boost::enable_shared_from_this<ClientConnection>> = {weak_this_ = {px = 0x7f981c4cf720, pn = {pi_ = 0x7f981c2feca0}}}, <boost::noncopyable_::noncopyable> = {<No data fields>}, 
  mIoService = @0x1333b10, 
  mSocket = {<boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >> = {<boost::asio::basic_io_object<boost::asio::stream_socket_service<boost::asio::ip::tcp>, true>> = {implementation = {<boost::asio::detail::reactive_socket_service_base::base_implementation_type> = {socket_ = -1, state_ = 0 '\000', reactor_data_ = 0x0}, protocol_ = {family_ = 2}}, 
        service_ = 0x1371560}, <boost::asio::socket_base> = {static message_peek = 2, static message_out_of_band = 1, static message_do_not_route = 4, static message_end_of_record = 128, 
        static max_connections = 128}, <No data fields>}, <No data fields>}, mStrand = {service_ = @0x13e5510, impl_ = 0x7f98080500a0},

ClientConnection.cpp:216是

  LOG_INFO("Close client[" << mClientId << "] socket connection");//line:216

mClientId是错误的值。看来此类已被破坏。

弱ptr,例如:

(gdb) frame 12
(gdb) p *(weak_this_.pn.pi_)
$3 = {_vptr.sp_counted_base = 0x957710 <vtable for boost::detail::sp_counted_impl_p<ClientConnection>+16>, use_count_ = {_M_i = 3}, weak_count_ = {_M_i = 2}}

boost_asio / example

我已经在互联网上进行搜索,找到https://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/example/http/server3/connection.cpp

示例中的注释如下:

int handle_read:

// If an error occurs then no new asynchronous operations are started. This
// means that all shared_ptr references to the connection object will
// disappear and the object will be destroyed automatically after this
// handler returns. The connection class's destructor closes the socket.

int handle_write:

// No new asynchronous operations are started. This means that all shared_ptr
// references to the connection object will disappear and the object will be
// destroyed automatically after this handler returns. The connection class's
// destructor closes the socket.

为什么?

(i)如果handle_read / handle_write中发生错误,是否应该在其他线程中使用此连接weak_ptr?
  (ii)ClientConnection类的生命周期是在Asio中,并且受Asio控制,我的代码有什么问题?

(iii)我认为它不能使用stand.post()和connection的weak_ptr来做某事。应该修改如下代码?

void ClientConnection::handle_read(const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
  if (!e)
  {
      //read data and use it
  }
  else { //error occurs 
      //closeSocket();
      //boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
      //cmd->setClient(this->weak_from_this());  //here set this connection weak_ptr
      //putCmd(cmd);  //do something in other thread.


      //just close socket
      boost::system::error_code error;
      mSocket.close(error);
  }
}

我在线,期待您的帮助。

谢谢。最好的祝福。

0 个答案:

没有答案