bad_weak_ptr 使用继承自 boost::asio::io_context::service 的类

Posted

技术标签:

【中文标题】bad_weak_ptr 使用继承自 boost::asio::io_context::service 的类【英文标题】:bad_weak_ptr while using class inheriting from boost::asio::io_context::service 【发布时间】:2018-06-10 15:43:14 【问题描述】:

我开始练习使用 boost asio 和 boost beast 来开发我自己的基本服务器和连接类。最近我遇到了 bad_weak_ptr 异常,我不知道如何管理这个问题。代码如下:

class server : public boost::asio::io_context::service
    
        tcp::endpoint endpoint boost::asio::ip::address_v6::any(), 7654 ;
        tcp::acceptor acceptor;
        boost::asio::strand<boost::asio::io_context::executor_type> strand;
        std::vector<std::weak_ptr<tcp_connection_ui>> connections;
    public:
        static const boost::asio::execution_context::id id;

        explicit tcp_server_ui(boost::asio::io_context& ioc)
            : boost::asio::io_context::service ioc 
            , acceptor ioc, endpoint 
            , strand ioc.get_executor() 
        
        

        void run()
        
            boost::asio::post(strand, [this] start_accept(); );
        

        void start_accept()
        
            tcp::socket socket acceptor.get_io_context() ;
            tcp_connection_ui::pointer new_connection =
                tcp_connection_ui::create(std::move(socket));

            connections.push_back(new_connection);

            acceptor.async_accept(new_connection->web_socket().next_layer(),
                boost::asio::bind_executor(strand, std::bind(
                    &tcp_server_ui::handle_accept,
                    this, new_connection, std::placeholders::_1)));
        

        void handle_accept(tcp_connection_ui::pointer new_connection,
            boost::system::error_code ec)
        
            if (!ec) 
                new_connection->run();
            

            start_accept();
        

        void broadcast(std::string&& msg)
        
            std::cout << '+' << std::endl;
            if (connections.empty())
                return;

            for (auto const & x : connections)
                x.lock()->enqueue_message(std::move(msg));
        
    ;

还有就是代码停止运行的地方:

class tcp_connection_ui : std::enable_shared_from_this<tcp_connection_ui>
    
    public:
        using pointer = std::shared_ptr<tcp_connection_ui>;

        static pointer create(tcp::socket socket)
        
            return std::make_shared<tcp_connection_ui>(tcp_connection_ui std::move(socket) );
        

        void run()
        
            ws.async_accept(boost::asio::bind_executor(strand, std::bind(
                &tcp_connection_ui::on_accept, shared_from_this(),
                std::placeholders::_1)));
         .../;

如果客户端尝试连接 server::handle_accept 中的值 shared_from_this 等于 _Wptr = empty。我认为我在理解 io_context::service 和/或 shared_from_this 功能时遇到了一些麻烦。任何帮助将不胜感激。

【问题讨论】:

你为什么从service派生?这看起来不对……服务只在最罕见的情况下才需要,实现典型的服务器不是其中之一。 这一行看起来有问题:x.lock()&gt;enqueue_message(std::move(msg)); 你没有检查lock 的返回值。而且您正在转移消息的所有权(因为移动)。如果循环多次运行会发生什么? 【参考方案1】:

基类必须公开继承:

class tcp_connection_ui : public std::enable_shared_from_this<tcp_connection_ui>

否则make_sharedshared_ptr 将不会注意到它并随后无法初始化“隐藏”的weak_ptr

【讨论】:

天啊……我有时很心烦意乱。非常感谢你。一点帮助,但节省了我很多时间!

以上是关于bad_weak_ptr 使用继承自 boost::asio::io_context::service 的类的主要内容,如果未能解决你的问题,请参考以下文章

shared_from_this使用boost :: asio抛出bad_weak_ptr

boost.variant 派生类型:不能使用复制构造函数

Boost::Python 为具有继承的类绑定

Boost学习笔记 progress_timer

使用自定义访问者时自定义类型的 Boost 变体失败(源自 boost::static_visitor)

boost: 使用自定义删除器序列化 shared_ptr