shared_from_this、asio 上的错误弱 ptr 异常

bad weak ptr exception on shared_from_this, asio

我知道这个问题已经在许多其他帖子中讨论过了。 特别是 this 似乎与我的问题相似并且也处理 boost::asio,但在我的情况下我已经有一个 shared_ptr 拥有调用 shared_from_this()[= 的对象15=]

有什么想法吗?

这是代码

node.h

#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED

#include <vector>
#include <string>
#include <memory>
#include <thread>

#include <boost/asio.hpp>
#include <boost/enable_shared_from_this.hpp>

typedef boost::asio::ip::tcp::socket tcp_socket;
typedef boost::asio::ip::tcp::acceptor tcp_acceptor;
typedef std::shared_ptr<tcp_socket> tcp_socket_ptr;

class Peer;

class InConnection;
typedef std::shared_ptr<InConnection> InConnection_ptr;

class AsioNode
{
    friend class InConnection;

private:
    int _port;
    std::vector<Peer> _peers;

    std::vector<tcp_socket_ptr> _peers_connections;

    boost::asio::io_service _io_service;
    tcp_acceptor _acceptor;

    std::thread _rcv_thread;

    static const std::string inter_mex_delimiter;

    void accept();

    void handle_accept(InConnection_ptr new_connection, const boost::system::error_code &error);

public:
    AsioNode(const std::vector<Peer> &peers, int port);

    void initialize_telecom();
};

class InConnection: public boost::enable_shared_from_this<InConnection>
{
private:
    tcp_socket _input_socket;
    boost::asio::streambuf _input_buffer;

    void handle_read(const boost::system::error_code &error, std::size_t nbytes);

public:
    InConnection(boost::asio::io_service &svc) : _input_socket(svc){};

    tcp_socket &socket() {return _input_socket;}

    void read();
};

class Peer{
private:
    int _port;
    std::string _host;

public:
    Peer(std::string host, int port) : _host(host), _port(port) {}

    int get_port() const {return _port;}
    std::string get_host() const {return _host;}
};

typedef std::shared_ptr<AsioNode> AsioNode_ptr;

#endif // NODE_H_INCLUDED

node.cpp (在方法 accept() 中,对于每个连接,我创建一个新的 InConnection 对象并将其存储在 shared_ptr 上)

#include <vector>
#include <string>
#include <iostream>
#include <ostream>
#include <memory>
#include <exception>

#include <boost/asio.hpp>
#include <boost/bind.hpp>

#include "node.h"

void InConnection::read()
{
    boost::asio::async_read_until(_input_socket, _input_buffer, AsioNode::inter_mex_delimiter,
                                  boost::bind(&InConnection::handle_read, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void InConnection::handle_read(const boost::system::error_code &error, std::size_t nbytes)
{
    if(!error)
    {
        // do things

        read();
    }
    else
        std::cout << "error in read " << error << std::endl;
}

const std::string AsioNode::inter_mex_delimiter = "end_message";

AsioNode::AsioNode(const std::vector<Peer> &peers, int port) :
    _port(port), _peers(peers), _acceptor(_io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
    _rcv_thread([&] {boost::asio::io_service::work work(_io_service); _io_service.run();})
{
    accept();
}

void AsioNode::initialize_telecom()
{
    boost::asio::ip::tcp::resolver resolver(_io_service);

    // initialize the client side (for gossiping packets)
    for (const auto &peer : _peers)
    {
        tcp_socket_ptr new_socket(new tcp_socket(_io_service));
        boost::system::error_code ec;
        auto endpoint = resolver.resolve(boost::asio::ip::tcp::resolver::query(peer.get_host(), std::to_string(peer.get_port())));
        boost::asio::connect(*new_socket, endpoint, ec);

        if(ec)
            std::cout << "error on connetctin" << std::endl;
        else{
         //   std::cout << _port << " connected to " << peer.get_port() << std::endl;
        }
        _peers_connections.push_back(new_socket);
    }
}

void AsioNode::accept()
{
    /* 
    * HERE i create the shared_ptr to the tcp connection
    *
    *
    */ 
    InConnection_ptr new_connection(new InConnection(_io_service));
    _acceptor.async_accept(new_connection->socket(),
                           boost::bind(&AsioNode::handle_accept, this, new_connection, boost::asio::placeholders::error));
}

void AsioNode::handle_accept(InConnection_ptr new_connection, const boost::system::error_code &error)
{
    if(!error)
    {
        std::cout << _port << " accept " << new_connection->socket().remote_endpoint().port() << std::endl;
        // start accepting the peer messages
        new_connection->read();
    }
    else
        std::cout << _port << " error " << error << " on accept" << std::endl;

    // listen for new peer connections
    accept();
}

要测试的简单演示 每个节点在一个端口上接受连接,并连接到其他三个节点

#include <iostream>
#include <vector>
#include <string>

#include "node.h"

int main()
{
    std::string localhost("127.0.0.1");
    int port1 = 10000;int port2 = 10001;int port3 = 10002;
    Peer peer1(localhost, port1), peer2(localhost, port2), peer3(localhost, port3);
    std::vector<Peer> peers1({peer2, peer3}), peers2({peer1, peer3}), peers3({peer1, peer2});

    // initialize the server side
    auto node1 = std::make_shared<AsioNode>(peers1, port1);
    auto node2 = std::make_shared<AsioNode>(peers2, port2);
    auto node3 = std::make_shared<AsioNode>(peers3, port3);

    node1->initialize_telecom();
    node2->initialize_telecom();
    node3->initialize_telecom();

    while(1);
}

问题是我混合命名空间 std(std::shared_ptr) 和 boost(boost::enable_shared_from_this)。

就我而言,我解决了从 boost::enable_shared_from_thisstd::enable_shared_from_this

的问题