Boost shared_ptr对象在获取值时遇到问题

时间:2014-11-13 00:24:17

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

好的......我花了太多时间。

我正在做的是建立一个连接列表,“陌生人”只是一个未经证实或被拒绝的连接,等待确认客户端收到消息。主机有这些陌生人的矢量作为boost :: shared_ptr,当一个被接受的陌生人被激活时,它变成了一个客户端,但那不是问题。

当收到连接时,会产生一个新的陌生人,但是在发送数据包时调用端点“(* it) - > getEndpoint()”时出现运行时错误,但这只是一个例子,它与其他值相同,例如“timed_out”。

这里是陌生人类,以及发送

的用法
class stranger : public boost::enable_shared_from_this<stranger> //a short lived object that sends the reply if their connection accepted / denied until an ack is received or timed out.
{
private:
  udp::endpoint end_p_;
  std::string data_;
  std::string name_;

  deadline_timer Timeout;
public:

  bool accepted = false; //public to check if this stranger is accepted or not.

  bool timed_out = false;

  //we assume the packet we are sending is accepting the connection because we have the name parameter.
  stranger(udp::endpoint end_p, std::string name, boost::asio::io_service &io_s)
    :Timeout(io_s)
    ,end_p_(end_p)
  {
    std::stringstream ss; //formatting the packet
    ss<<(char)(con_rep_accepted)<<0<<0; //packettype, 2 bytes for pak num(its 0 because its the connection)
    data_ = ss.str();
    name = name_;
    accepted = true;
    timed_out = false;

    Timeout.expires_from_now(boost::posix_time::seconds(5));
    Timeout.async_wait(boost::bind(&stranger::doTimeout, this));
  }
  //we assume the packet we are sending is denying the connection because there is no name.
  stranger(udp::endpoint end_p , boost::asio::io_service& io_s)
    :Timeout(io_s)
  {
    end_p_ = end_p;
    std::stringstream ss; //formatting the packet
    ss<<(char)(con_rep_denied)<<0<<0; //1 byte for packet type, 2 bytes for pak num(its 0 because its the connection)
    data_ = ss.str();
    accepted = false;
    timed_out = false;

    Timeout.expires_from_now(boost::posix_time::seconds(5));
    Timeout.async_wait(boost::bind(&stranger::doTimeout, this));
  }

  void doTimeout()
  {
    std::cout<<"timed.\n";
    timed_out = true;
  }


  udp::endpoint getEndpoint(){return end_p_;} //to compare endpoints

  std::string getData(){return data_;}

  std::string getName(){return name_;}

  ~stranger(){Timeout.cancel();}
};

当我获得运行时调试器指向的位置。 客户端现在基本上与陌生人完全相同,没有要发送的游戏数据。它们也是shared_ptrs的向量。

//Everything that the server receives
void Host_State::Receive()
{
socket_.async_receive_from(
  boost::asio::buffer(in_data,1024), sender_endpoint_,
  [this](boost::system::error_code ec, std::size_t bytes)
  {
    if (!ec && bytes >= 3 ) //the header is 3 bytes, and the smallest usable packet is 3 bytes.
    {

      int pak_type = (int)(in_data[0]);

      unsigned short packet_num = (in_data[1] << 8) | in_data[2]; //the number in which order it is from

      for(auto it = clients.begin(); it!=clients.end(); it++)
        //HERE!------------------------
        if((*it)->getEndpoint() == sender_endpoint_) //<-debugger points here
        //------------------------
        {

使用windows,gcc 4.8.1,提升1.57.0。 调试转储:

#0 00435E5C boost::shared_ptr<client>::operator->(this=0x6e6f6974) (C:/boost_1_57_0/boost/smart_ptr/shared_ptr.hpp:648)
#1 00406394 Host_State::__lambda1::operator() (__closure=0x28fc00, ec=..., bytes=67) (C:\Users\poteto\Desktop\pixely_trenches\Sources\Server.cpp:26)
#2 00408EB1 boost::asio::detail::binder2<Host_State::Receive()::__lambda1, boost::system::error_code, unsigned int>::operator()(void)(this=0x28fc00) (C:/boost_1_57_0/boost/asio/detail/bind_handler.hpp:127)
#3 00408E61 boost::asio::asio_handler_invoke<boost::asio::detail::binder2<Host_State::Receive()::__lambda1, boost::system::error_code, unsigned int> >(boost::asio::detail::binder2<Host_State::Receive()::__lambda1, boost::system::error_code, unsigned int> &, ...)(function=...) (C:/boost_1_57_0/boost/asio/handler_invoke_hook.hpp:69)
#4 00408D55 boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder2<Host_State::Receive()::__lambda1, boost::system::error_code, unsigned int>, Host_State::Receive()::__lambda1>(boost::asio::detail::binder2<Host_State::Receive()::__lambda1, boost::system::error_code, unsigned int> &, Host_State::__lambda1 &)(function=..., context=...) (C:/boost_1_57_0/boost/asio/detail/handler_invoke_helpers.hpp:37)
#5 00408993 boost::asio::detail::win_iocp_socket_recvfrom_op<boost::asio::mutable_buffers_1, boost::asio::ip::basic_endpoint<boost::asio::ip::udp>, Host_State::Receive()::__lambda1>::do_complete(boost::asio::detail::io_service_impl *, boost::asio::detail::operation *, const boost::system::error_code &, std::size_t)(owner=0x9cff48, base=0x9c3510, result_ec=..., bytes_transferred=67) (C:/boost_1_57_0/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp:104)
#6 00423CD0 boost::asio::detail::win_iocp_operation::complete(this=0x9c3510, owner=..., ec=..., bytes_transferred=67) (C:/boost_1_57_0/boost/asio/detail/win_iocp_operation.hpp:46)
#7 00424DF5 boost::asio::detail::win_iocp_io_service::do_one(this=0x9cff48, block=true, ec=...) (C:/boost_1_57_0/boost/asio/detail/impl/win_iocp_io_service.ipp:405)
#8 00424AA1 boost::asio::detail::win_iocp_io_service::run(this=0x9cff48, ec=...) (C:/boost_1_57_0/boost/asio/detail/impl/win_iocp_io_service.ipp:164)
#9 0041E65A boost::asio::io_service::run(this=0x511391c) (C:/boost_1_57_0/boost/asio/impl/io_service.ipp:59)
#10 0041645E    _fu15___ZSt4cout() (C:/Users/poteto/Desktop/pixely_trenches/Sources/Host.h:232)
#11 00405A87    ChangeState() (C:\Users\poteto\Desktop\pixely_trenches\Sources\main.cpp:44)
#12 00405C90    SDL_main(argc=argc@entry=1, argv=argv@entry=0x3b0008) (C:\Users\poteto\Desktop\pixely_trenches\Sources\main.cpp:98)
#13 0040C11C    console_main(argc=argc@entry=1, argv=argv@entry=0x3b0008) (../src/main/windows/SDL_windows_main.c:140)
#14 0040C2DD    WinMain@16(hInst=0x400000, hPrev=0x0, szCmdLine=0x9d3ab4 "", sw=10) (../src/main/windows/SDL_windows_main.c:177)
#15 00448C1B    main () (??:??)

2 个答案:

答案 0 :(得分:0)

当你是队列异步活动时,你想在绑定中使用shared_ptr,这样只要有未完成的活动,对象的生命就会延长。

你的问题在于你使用boost :: bind。

例如:

Timeout.async_wait(boost::bind(&stranger::doTimeout, shared_from_this()));

是正确的模式。

答案 1 :(得分:0)

这是一个代码事故,有迭代器失效:

for(auto it= clients.begin(); it!=clients.end(); )
{
  if((*it).timed_out)
  {
    clients.erase(it);
  }

  ++it; //I should've put this into an else.
}

耶稣基督,问题也在于因为我有我的&#34; in_data []&#34;初始化就像没有数字的那样。我不是一个聪明的程序员......