了解共享指针的问题(生命周期,作为参数传递)

Understanding issue with shared pointers (Lifetime, passing as parameter)

我试着从boost asio chat example开始,衍生出一个自己的网络程序。不幸的是,我在理解真正发生的事情时遇到了一些问题。我试图将我的程序减少到绝对最低限度。服务器 class 等待传入连接并创建会话对象来处理连接。这是服务器的代码:

#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;
}

此代码 运行s 符合预期,但当我尝试调整一些东西并尝试一些操作时,我发现我不明白共享指针何时真正创建和删除以及在哪里它们被存储。例如,我尝试将 std::make_shared<Session>(std::move(m_oSocket))->StartSession(); 更改为 std::make_shared<Session>(std::move(m_oSocket));,并在 Session class 的构造函数中添加了 StartSession();。如果我 运行 代码,它会抛出

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

这大概发生在 auto self(shared_from_this());。但我不明白为什么?我应该在我的代码中更改什么?所以我认为我的问题是我不明白如何正确使用 shared_ptr ,如何在这些结构中使用它,我可以在哪里访问它以及如何使其可访问。此外,不清楚为什么我有时必须使用 this 以及何时使用 shared_from_this()。是否有好的教程或简单的经验法则?

我也不清楚,为什么有些人使用 lambda 函数符号,而有些人使用 boost::bind 符号,有什么区别?

所以请原谅我的新手问题,我试图在教程中找到一些信息,但只对这些共享指针和 boost::asio 感到困惑。好像总是做些奇怪的事情。

你得到 std::bad_weak_ptr 因为在 Session 的构建过程中没有 shared_ptr 拥有 this。您仍在 make_shared 的主体中,并且尚未完成 shared_ptr 的创建。

shared_from_this()只能从Session的实例中获得,它是一个成员函数。您通过派生自 std::enable_shared_from_this.

继承了它

lambda 是用 self 的副本构造的,并且 Session 的成员可用,就好像 this 也指向 Session 对象,而不是lambda 对象,因为 this 捕获