了解共享指针的问题(生命周期,作为参数传递) [英] Understanding issue with shared pointers (Lifetime, passing as parameter)

查看:335
本文介绍了了解共享指针的问题(生命周期,作为参数传递)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试从boost asio聊天示例开始,并派生自己的联网程序.不幸的是,我在理解实际情况时遇到了一些问题.我试图将程序减少到最低限度.服务器类等待传入的连接,并创建一个会话对象来处理连接.这是服务器的代码:

I tried to start with the boost asio chat example and derive an own networking program. Unfortunately I have some problem understanding what really happens. I tried to reduce my program to an absolute minimum. A server class waits for incoming connections and creates a session object to handle the connection. This is the code of the server:

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

这段代码按预期运行,但是当我尝试调整一些东西并进行一些调整时,我发现我不理解何时真正创建和删除共享指针以及将它们存储在何处.例如,我尝试将std::make_shared<Session>(std::move(m_oSocket))->StartSession();更改为std::make_shared<Session>(std::move(m_oSocket));并将StartSession();添加到Session类的构造函数中.如果我运行代码,则会抛出

This code runs as intended, but as I tried to adjust some things and to play a little bit around I figured out that I don't understand when shared pointers are really created and deleted and where they are stored. For example I tried to change the std::make_shared<Session>(std::move(m_oSocket))->StartSession(); to std::make_shared<Session>(std::move(m_oSocket)); and added the StartSession(); in the constructor of the Session class. If I run the code then, it throws

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().有没有很好的教程或简单的经验法则?

This presumably happens in auto self(shared_from_this());. But I don't understand why? What should I change in my code? So I think my problem is that I don't understand how to use the shared_ptr correctly, how to use it in these constructions, where I can access it and how to make it accessible. Further it is not clear why I sometimes have to user this and when to use shared_from_this(). Is there a good tutorial, or a simple rule of thumb?

我也不清楚,为什么有些用户使用lambda函数表示法,而有些boost::bind表示法又有什么区别呢?

It is also unclear to me, why some user the lambda function notation, and some the boost::bind notation and what are the differences?

因此,请原谅我的新手问题,我试图在教程中找到一些信息,但仅与这些共享指针和boost :: asio混淆.似乎总是在做奇怪的事情.

So please forgive my newbie questions, I tried to find some information in tutorials but am only confused with these shared pointers and boost::asio. It seems always to do strange things.

推荐答案

之所以得到std::bad_weak_ptr,是因为在构建Session时没有shared_ptr拥有this.您仍然位于make_shared的正文中,并且尚未完成创建shared_ptr的过程.

You get std::bad_weak_ptr because there is no shared_ptr owning this during the construction of your Session. You are still in the body of make_shared, and it hasn't finished creating the shared_ptr.

shared_from_this()仅在Session的实例中可用,它是成员函数.您是从std::enable_shared_from_this派生而来的.

shared_from_this() is only available from the instance of Session, it is a member function. You have inherited it by deriving from std::enable_shared_from_this.

lambda由self的副本构造,并且Session的成员可用,因为this由于捕获了this而还指向Session对象,而不是lambda对象,因此可用-c

The lambdas are constructed with copies of self, and the members of Session are available as-if this also pointed to the Session object, not the lambda object, because of the this capture

这篇关于了解共享指针的问题(生命周期,作为参数传递)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆