Saya mencoba memulai dengan contoh boost asio chat dan mendapatkan program jaringan sendiri. Sayangnya saya memiliki beberapa masalah dalam memahami apa yang sebenarnya terjadi. Saya mencoba untuk mengurangi program saya ke minimum absolut. Kelas server menunggu koneksi masuk dan membuat objek sesi untuk menangani koneksi. Ini adalah kode servernya:

#include <cstdint>
#include <iostream>
#include <sstream>
#include <memory>
#include <vector>

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

class Session : public std::enable_shared_from_this<Session>
{
public:
    Session(boost::asio::ip::tcp::socket __oSocket);
    virtual ~Session();
    void StartSession();
private:
    void StartRecv();
    std::vector<int32_t> m_vecSetupReceiveBuffer;
    boost::asio::ip::tcp::socket m_oSocket;
};

Session::Session(boost::asio::ip::tcp::socket __oSocket) :
    m_vecSetupReceiveBuffer({2}),
    m_oSocket(std::move(__oSocket))
{    }

Session::~Session()
{
    std::cout << "Deleted session" << std::endl;
}

void Session::StartSession()
{
    auto self(shared_from_this());
    std::cout << "StartSession()" << std::endl;
    boost::asio::async_write(m_oSocket, boost::asio::buffer(m_vecSetupReceiveBuffer),
    [this, self](boost::system::error_code _oError, std::size_t)
    {
        std::cout << m_vecSetupReceiveBuffer.size() << std::endl;
        StartRecv();
    });
}

void Session::StartRecv()
{
    auto self(shared_from_this());
    std::cout << "StartRecv()" << std::endl;
    boost::asio::async_read(m_oSocket, boost::asio::buffer(m_vecSetupReceiveBuffer),
    [this, self](boost::system::error_code _oError, std::size_t)
    {});
}

class Server
{
public:
    Server(boost::asio::io_service& _rIOService, uint32_t _nPort);
    virtual ~Server();
private:
    void StartAccept();
    boost::asio::ip::tcp::acceptor m_oAcceptor;
    boost::asio::ip::tcp::socket m_oSocket;
};

Server::Server(boost::asio::io_service& _rIOService, uint32_t _nPort) :
    m_oAcceptor(_rIOService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), _nPort)),
    m_oSocket(_rIOService)
{
    StartAccept();
}

Server::~Server()
{}

void Server::StartAccept()
{
    m_oAcceptor.async_accept(m_oSocket,
    [this](boost::system::error_code _oError)
    {
        std::make_shared<Session>(std::move(m_oSocket))->StartSession();
        StartAccept();
    });
}


int main(int argc, char* argv[])
{
    boost::asio::io_service _oIOServerService;
    std::shared_ptr<Server> _pServer(std::make_shared<Server>(_oIOServerService, 2000));
    _oIOServerService.run();
    return 0;
}

Kode ini berjalan sebagaimana dimaksud, tetapi ketika saya mencoba untuk menyesuaikan beberapa hal dan bermain-main sedikit, saya menemukan bahwa saya tidak mengerti kapan pointer bersama benar-benar dibuat dan dihapus dan di mana mereka disimpan. Misalnya saya mencoba mengubah std::make_shared<Session>(std::move(m_oSocket))->StartSession(); menjadi std::make_shared<Session>(std::move(m_oSocket)); dan menambahkan StartSession(); di konstruktor kelas Sesi. Jika saya menjalankan kode itu, itu melempar

terminate called after throwing an instance of 'std::bad_weak_ptr'
what():  bad_weak_ptr
Aborted (core dumped)

Ini mungkin terjadi di auto self(shared_from_this());. Tapi aku tidak mengerti kenapa? Apa yang harus saya ubah dalam kode saya? Jadi saya pikir masalah saya adalah saya tidak mengerti bagaimana menggunakan shared_ptr dengan benar, bagaimana menggunakannya dalam konstruksi ini, di mana saya dapat mengaksesnya dan bagaimana membuatnya dapat diakses. Selanjutnya tidak jelas mengapa saya terkadang harus menggunakan this dan kapan harus menggunakan shared_from_this(). Apakah ada tutorial yang bagus, atau aturan praktis yang sederhana?

Juga tidak jelas bagi saya, mengapa beberapa pengguna notasi fungsi lambda, dan beberapa notasi boost::bind dan apa perbedaannya?

Jadi mohon maafkan pertanyaan pemula saya, saya mencoba mencari beberapa informasi dalam tutorial tetapi saya hanya bingung dengan petunjuk dan dorongan yang dibagikan ini::asio. Tampaknya selalu melakukan hal-hal aneh.

2
Martin Herrmann 5 Januari 2018, 11:50

1 menjawab

Jawaban Terbaik

Anda mendapatkan std::bad_weak_ptr karena tidak ada shared_ptr yang memiliki this selama konstruksi Session Anda. Anda masih berada di tubuh make_shared, dan belum selesai membuat shared_ptr.

shared_from_this() hanya tersedia dari instance Session, ini adalah fungsi anggota. Anda mewarisinya dengan menurunkan dari std::enable_shared_from_this.

Lambda dibuat dengan salinan self, dan anggota Session tersedia seolah-olah this juga menunjuk ke objek Session, bukan objek lambda, karena penangkapan this

0
Caleth 5 Januari 2018, 11:38