• <bdo id='8I0Y4'></bdo><ul id='8I0Y4'></ul>
    <tfoot id='8I0Y4'></tfoot>

    <small id='8I0Y4'></small><noframes id='8I0Y4'>

    <i id='8I0Y4'><tr id='8I0Y4'><dt id='8I0Y4'><q id='8I0Y4'><span id='8I0Y4'><b id='8I0Y4'><form id='8I0Y4'><ins id='8I0Y4'></ins><ul id='8I0Y4'></ul><sub id='8I0Y4'></sub></form><legend id='8I0Y4'></legend><bdo id='8I0Y4'><pre id='8I0Y4'><center id='8I0Y4'></center></pre></bdo></b><th id='8I0Y4'></th></span></q></dt></tr></i><div id='8I0Y4'><tfoot id='8I0Y4'></tfoot><dl id='8I0Y4'><fieldset id='8I0Y4'></fieldset></dl></div>

    1. <legend id='8I0Y4'><style id='8I0Y4'><dir id='8I0Y4'><q id='8I0Y4'></q></dir></style></legend>

      1. shared_from_this 导致 bad_weak_ptr

        shared_from_this causing bad_weak_ptr(shared_from_this 导致 bad_weak_ptr)

            <tbody id='KG5tE'></tbody>

          • <bdo id='KG5tE'></bdo><ul id='KG5tE'></ul>
              <legend id='KG5tE'><style id='KG5tE'><dir id='KG5tE'><q id='KG5tE'></q></dir></style></legend>

              <small id='KG5tE'></small><noframes id='KG5tE'>

              <tfoot id='KG5tE'></tfoot>
              <i id='KG5tE'><tr id='KG5tE'><dt id='KG5tE'><q id='KG5tE'><span id='KG5tE'><b id='KG5tE'><form id='KG5tE'><ins id='KG5tE'></ins><ul id='KG5tE'></ul><sub id='KG5tE'></sub></form><legend id='KG5tE'></legend><bdo id='KG5tE'><pre id='KG5tE'><center id='KG5tE'></center></pre></bdo></b><th id='KG5tE'></th></span></q></dt></tr></i><div id='KG5tE'><tfoot id='KG5tE'></tfoot><dl id='KG5tE'><fieldset id='KG5tE'></fieldset></dl></div>

                • 本文介绍了shared_from_this 导致 bad_weak_ptr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我正在尝试在 asio 中保留已连接客户端的列表.我已经改编了文档中的聊天服务器示例 (http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/example/cpp03/chat/chat_server.cpp)这是我结束的重要部分与:

                  I am trying to keep a list of connected clients in asio. I have adapted the chat server example from the docs (http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/example/cpp03/chat/chat_server.cpp) and here's the important part of what I ended up with:

                  #include <iostream>
                  #include <boost/bind.hpp>
                  #include <boost/shared_ptr.hpp>
                  #include <boost/enable_shared_from_this.hpp>
                  #include <boost/asio.hpp>
                  #include <set>
                  
                  using boost::asio::ip::tcp;
                  
                  class tcp_connection;
                  
                  std::set<boost::shared_ptr<tcp_connection>> clients;
                  
                  void add_client(boost::shared_ptr<tcp_connection> client)
                  {
                      clients.insert(client);
                  }
                  
                  class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
                  {
                  public:
                      tcp_connection(boost::asio::io_service& io_service) : socket_(io_service)
                      {
                      }
                  
                      tcp::socket socket_;
                  
                      void start()
                      {
                          add_client(shared_from_this());
                      }
                  
                      tcp::socket& socket()
                      {
                          return socket_;
                      }
                  };
                  
                  class tcp_server
                  {
                  public:
                      tcp_server(boost::asio::io_service& io_service)
                          : io_service_(io_service),
                          acceptor_(io_service, tcp::endpoint(tcp::v4(), 6767))
                      {
                          tcp_connection* new_connection = new tcp_connection(io_service_);
                          acceptor_.async_accept(new_connection->socket(),
                                               boost::bind(&tcp_server::start_accept, this, new_connection,
                                                           boost::asio::placeholders::error));
                      }
                  
                  private:
                      void start_accept(tcp_connection* new_connection,
                                        const boost::system::error_code& error)
                      {
                          if (!error)
                          {
                              new_connection->start();
                              new_connection = new tcp_connection(io_service_);
                              acceptor_.async_accept(new_connection->socket(),
                                                     boost::bind(&tcp_server::start_accept, this, new_connection,
                                                                 boost::asio::placeholders::error));
                          }
                      }
                  
                      boost::asio::io_service& io_service_;
                      tcp::acceptor acceptor_;
                  };
                  
                  int main()
                  {
                      try
                      {
                          boost::asio::io_service io_service;
                          tcp_server server(io_service);
                          io_service.run();
                      }
                      catch (std::exception& e)
                      {
                          std::cerr << "Exception: " << e.what() << "
                  ";
                      }
                  
                      return 0;
                  }
                  

                  在调用 shared_from_this() 时,我的服务器崩溃并显示以下消息:

                  At the call to shared_from_this(), my server crashes with the message:

                  异常:tr1::bad_weak_ptr

                  Exception: tr1::bad_weak_ptr

                  我进行了一些搜索,看起来 shared_from_this() 非常特别,但我似乎无法准确找到我需要更改的内容.

                  I have done some searching and it appears shared_from_this() is pretty particular, but I can't seem to find exactly what I need to change.

                  推荐答案

                  John Zwinck 的基本分析是:

                  John Zwinck's essential analysis is spot on:

                  错误在于您在没有 shared_ptr 指向的对象上使用 shared_from_this() .这违反了 shared_from_this() 的先决条件,即至少一个 shared_ptr 必须已经创建(并且仍然存在)指向 this.

                  The bug is that you're using shared_from_this() on an object which has no shared_ptr pointing to it. This violates a precondition of shared_from_this(), namely that at least one shared_ptr must already have been created (and still exist) pointing to this.

                  然而,他的建议在 Asio 代码中似乎完全离题且危险.

                  However, his advice seems completely beside the point and dangerous in Asio code.

                  您应该通过 - 实际上 - 首先不处理指向 tcp_connection 的原始指针,而是始终使用 shared_ptr 来解决此问题.

                  You should solve this by - indeed - not handling raw pointers to tcp_connection in the first place but always using shared_ptr instead.

                  boost::bind 有一个很棒的功能,它绑定到 shared_ptr<> 就好了,所以只要一些异步操作,它就会自动保持指向的对象处于活动状态正在对其进行操作.

                  boost::bind has the awesome feature that it binds to shared_ptr<> just fine so it automagically keeps the pointed to object alive as long as some asynchronous operation is operating on it.

                  这 - 在您的示例代码中 - 意味着您不需要 clients 向量,与约翰的回答相反:

                  This - in your sample code - means you don't need the clients vector, going the opposite way from John's answer:

                  void start_accept()
                  {
                      tcp_connection::sptr new_connection = boost::make_shared<tcp_connection>(io_service_);
                      acceptor_.async_accept(new_connection->socket(),
                              boost::bind(
                                  &tcp_server::handle_accept,
                                  this, new_connection, asio::placeholders::error
                              )
                          );
                  }
                  
                  void handle_accept(tcp_connection::sptr client, boost::system::error_code const& error)
                  {
                      if (!error)
                      {
                          client->start();
                          start_accept();
                      }
                  }
                  

                  我已经包含了一个示例,它使 tcp_connection 做一些琐碎的工作(它每秒循环向客户端写入hello world",直到客户端断开连接.当它断开连接时,您可以查看正在运行的 tcp_connection 操作的析构函数:

                  I've included a sample that makes tcp_connection do some trivial work (it loops writing 'hello world' to the client each second, until the client drops the connection. When it does, you can see the destructor of the tcp_connection operation being run:

                  生活在 Coliru

                  #include <iostream>
                  #include <boost/bind.hpp>
                  #include <boost/make_shared.hpp>
                  #include <boost/enable_shared_from_this.hpp>
                  #include <boost/asio.hpp>
                  #include <boost/thread.hpp>
                  
                  namespace asio = boost::asio;
                  using asio::ip::tcp;
                  
                  class tcp_connection : public boost::enable_shared_from_this<tcp_connection>
                  {
                  public:
                      typedef boost::shared_ptr<tcp_connection> sptr;
                  
                      tcp_connection(asio::io_service& io_service) : socket_(io_service), timer_(io_service)
                      {
                      }
                  
                      void start()
                      {
                          std::cout << "Created tcp_connection session
                  ";
                  
                          // post some work bound to this object; if you don't, the client gets
                          // 'garbage collected' as the ref count goes to zero
                          do_hello();
                      }
                  
                      ~tcp_connection() {
                          std::cout << "Destroyed tcp_connection
                  ";
                      }
                  
                      tcp::socket& socket()
                      {
                          return socket_;
                      }
                  
                    private:
                      tcp::socket socket_;
                      asio::deadline_timer timer_;
                  
                      void do_hello(boost::system::error_code const& ec = {}) {
                          if (!ec) {
                              asio::async_write(socket_, asio::buffer("Hello world
                  "),
                                      boost::bind(&tcp_connection::handle_written, shared_from_this(), asio::placeholders::error, asio::placeholders::bytes_transferred)
                                  );
                          }
                      }
                  
                      void handle_written(boost::system::error_code const& ec, size_t /*bytes_transferred*/) {
                          if (!ec) {
                              timer_.expires_from_now(boost::posix_time::seconds(1));
                              timer_.async_wait(boost::bind(&tcp_connection::do_hello, shared_from_this(), asio::placeholders::error));
                          }
                      }
                  };
                  
                  class tcp_server
                  {
                  public:
                      tcp_server(asio::io_service& io_service)
                          : io_service_(io_service),
                            acceptor_(io_service, tcp::endpoint(tcp::v4(), 6767))
                      {
                          start_accept();
                      }
                  
                  private:
                      void start_accept()
                      {
                          tcp_connection::sptr new_connection = boost::make_shared<tcp_connection>(io_service_);
                          acceptor_.async_accept(new_connection->socket(),
                                  boost::bind(
                                      &tcp_server::handle_accept,
                                      this, new_connection, asio::placeholders::error
                                  )
                              );
                      }
                  
                      void handle_accept(tcp_connection::sptr client, boost::system::error_code const& error)
                      {
                          if (!error)
                          {
                              client->start();
                              start_accept();
                          }
                      }
                  
                      asio::io_service& io_service_;
                      tcp::acceptor acceptor_;
                  };
                  
                  int main()
                  {
                      try
                      {
                          asio::io_service io_service;
                          tcp_server server(io_service);
                  
                          boost::thread(boost::bind(&asio::io_service::run, &io_service)).detach();
                  
                          boost::this_thread::sleep_for(boost::chrono::seconds(4));
                          io_service.stop();
                      }
                      catch (std::exception& e)
                      {
                          std::cerr << "Exception: " << e.what() << "
                  ";
                      }
                  }
                  

                  典型输出:

                  sehe@desktop:/tmp$ time (./test& (for a in {1..4}; do nc 127.0.0.1 6767& done | nl&); sleep 2; killall nc; wait)
                  Created tcp_connection session
                  Created tcp_connection session
                       1  Hello world
                  Created tcp_connection session
                       2  Hello world
                  Created tcp_connection session
                       3  Hello world
                       4  Hello world
                       5  Hello world
                       6  Hello world
                       7  Hello world
                       8  Hello world
                       9  Hello world
                      10  Hello world
                      11  Hello world
                      12  Hello world
                      13  
                  Destroyed tcp_connection
                  Destroyed tcp_connection
                  Destroyed tcp_connection
                  Destroyed tcp_connection
                  Destroyed tcp_connection
                  
                  real    0m4.003s
                  user    0m0.000s
                  sys 0m0.015s
                  

                  这篇关于shared_from_this 导致 bad_weak_ptr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                  相关文档推荐

                  How to limit the number of running instances in C++(C++中如何限制运行实例的数量)
                  Using boost::asio::async_read with stdin?(将 boost::asio::async_read 与 stdin 一起使用?)
                  How to find out what dependencies (i.e other Boost libraries) a particular Boost library requires?(如何找出特定 Boost 库需要哪些依赖项(即其他 Boost 库)?)
                  What#39;s the purpose of a leading quot;::quot; in a C++ method call(引导“::的目的是什么?在 C++ 方法调用中)
                  Boost Spirit x3: parse into structs(Boost Spirit x3:解析为结构体)
                  How boost auto-linking makes choice?(boost自动链接如何做出选择?)
                      <bdo id='48MXL'></bdo><ul id='48MXL'></ul>
                      <legend id='48MXL'><style id='48MXL'><dir id='48MXL'><q id='48MXL'></q></dir></style></legend>

                      <small id='48MXL'></small><noframes id='48MXL'>

                      • <tfoot id='48MXL'></tfoot>

                          <i id='48MXL'><tr id='48MXL'><dt id='48MXL'><q id='48MXL'><span id='48MXL'><b id='48MXL'><form id='48MXL'><ins id='48MXL'></ins><ul id='48MXL'></ul><sub id='48MXL'></sub></form><legend id='48MXL'></legend><bdo id='48MXL'><pre id='48MXL'><center id='48MXL'></center></pre></bdo></b><th id='48MXL'></th></span></q></dt></tr></i><div id='48MXL'><tfoot id='48MXL'></tfoot><dl id='48MXL'><fieldset id='48MXL'></fieldset></dl></div>

                              <tbody id='48MXL'></tbody>