在销毁此对象所指向的对象之后,将调用shared_from_this():C ++ ASIO [英] shared_from_this() is called after object pointing by this is destroyed: C++ ASIO

查看:64
本文介绍了在销毁此对象所指向的对象之后,将调用shared_from_this():C ++ ASIO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试开发ASIO应用程序,并已引用聊天服务器

I am tryin to develop ASIO Application and have referred Chat-Server

当我的 CServer Object 销毁时,它会导致 CSerSessionsManager Object 销毁-它持有指向所有活动聊天会话的共享指针.这也会导致所有活动的 CSerCession对象也被破坏.

When my CServer Object destructs it causes CSerSessionsManager Object to destruct- which holds shared pointer to all active chat sessions. It causes all active CSerCession Objects to destroy as well.

请参阅定义

class CServer {

    CServer(asio::io_service& io_service, const std::string serIdentity, std::string IP, const std::string port);
    ~CServer();
.....

private:

    mutable tcp::acceptor acceptor_; // only in the listener
    asio::io_service& io_;
    CSerSessionsManager mng_;

......

};


class CSerSessionsManager{
public:
    CSerSessionsManager();
    ~CSerSessionsManager();

    void addSession(sessionPtr session);
    void dropSession(sessionPtr session);

private:

    std::set<sessionPtr> sessions_; //Active Sessions : Online Info

};

class CSerSession : public std::enable_shared_from_this<CSerSession>{
    public:
        CSerSession(asio::io_service& io_service, CSerSessionsManager& mng, const std::string serverID,
            const std::string ip, const std::string port);
        ~CSerSession();

.......
    private:

        mutable tcp::socket socket_;   // client connection
        CSerSessionsManager& manager_;
......

    };

但是,由于 CSerSession对象被破坏,因此导致活动会话发生 read错误,并调用了 read_handle().

But since the CSerSession Object destroys it causes read error for active session and read_handle() is called.

void CSerSession::handle_read(const asio::error_code& error /*error*/, size_t bytes_transferred /*bytes_transferred*/)
{
    if (!error)
    {
        //do Something
    }
    else
    {
        DEBUG_MSG("Read Error Detected : " << error.message());
        //Check If shared_from_this() is valid or not
        try
        {

            //if (error == asio::error::operation_aborted)
            manager_.dropSession(shared_from_this()); //Exception Here
        }
        catch (const std::bad_weak_ptr& e)
        {
            DEBUG_MSG(e.what());
            throw e;
        }
        return;
    }
}

代码在此处异常处引发异常.调试时显示:

The code throws exception at Exception Here. On debugging it shows:

this    0x0044697c {socket_={...} manager_={sessions_={ size=??? } sessionPool_={ size=??? } } ip_=<Error reading characters of string.> ...}
std::enable_shared_from_this<channel::CSerSession>  {_Wptr={[deleter and allocator]={_Uses=??? _Weaks=??? } } }
socket_ {...}
manager_    {sessions_={ size=??? } sessionPool_={ size=??? } }
ip_ <Error reading characters of string.>
port_   <Error reading characters of string.>
parentServer_   <Error reading characters of string.>
servicedClientID_   <Error reading characters of string.>
serSessioID_    <Error reading characters of string.>
serSessionIdentifier_   <Error reading characters of string.>
privilege_  -274
serSessionIdentitySet_  true (238)
msg_    {received_=0x00446a77 "þîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþî... }
writeQueue_ { size=4277075694 }

我看到调试器显示 std :: enable_shared_from_this< channel :: CSerSession>时,正在调用 manager_.dropSession(shared_from_this()); .{_Wptr = {[deleter and allocator] = {_ Uses = ???_Weaks = ???} .

I can see that manager_.dropSession(shared_from_this()); is being called when debugger shows std::enable_shared_from_this<channel::CSerSession> {_Wptr={[deleter and allocator]={_Uses=??? _Weaks=??? }.

由于设置了 read_error ,因此在销毁 CSerSession对象之后调用了它.错误的默认行为是破坏会话,因此必须强制使用 manager_.dropSession(shared_from_this()); .

It is being called after the destruction of CSerSession object as read_error is being set. Default behavior on error is to destroy the session and hence manager_.dropSession(shared_from_this()); is mandatory there.

问题是此对象的破坏导致 read_error ,这又试图通过 manager_.dropSession(shared_from_this());销毁同一对象.

The problem is that the destruction of this object causing read_error which again tries to destroy the same object via manager_.dropSession(shared_from_this());

如何解决该错误?

总结问题:

聊天会话中的任何错误都应设置 read error ,然后调用 read_handle(),然后通过 manager_.dropSession(shared_from_this())破坏聊天会话.;

Any error during chat session should set read error and read_handle() should be called which then destroys chat session via manager_.dropSession(shared_from_this());

但是,当我的聊天会话 CSerSession对象超出范围时,即调用了析构函数,这也会导致 read error 处于活动状态.因此,再次调用 manager_.dropSession(shared_from_this()); .

But when my chat session CSerSession Object is going out of scope i.e. destructor is called, it is also causing read error as it was active. So again manager_.dropSession(shared_from_this()); is being called.

因此基本上是从析构函数间接调用 shared_from_this().

So basically shared_from_this() is being indirectly called from destructor.

推荐答案

从套接字读取并设置 CSerSession :: handle_read 读取处理程序时,应绑定 shared_from_this()代替 this .

When you read from socket and set CSerSession::handle_read read handler, you should bind shared_from_this() instead of this.

例如,您的 async_read()应该看起来像这样:

For example, your async_read() should look similar to this:

socket_.async_read(boost::asio::buffer(...),
                   std::bind(&CSerSession::handle_read, shared_from_this(),
                             std::placeholder::_1, 
                             std::placeholder::_2);

您观察到的问题是由事件队列的性质引起的.当销毁 CSerSession 时,事件队列中的某些事件可能会将 this 指针保留为已破坏的对象.因此,开发人员建议使用 shared_ptr shared_from_this().当您传递 shared_ptr 而不是 this 时,您可以使感兴趣的对象保持活动状态.

The problem you observe is caused by the nature of event queue. When you destroy CSerSession some events in the event queue may keep this pointer to object that was already destructed. Thats why developers recommend using shared_ptr and shared_from_this(). When you pass shared_ptr instead of this you keep object of interest alive.

回复您的修改:

您说的是从析构函数间接调用 manager_.dropSession(shared_from_this()); .但是,如果 read_handle()仍然保留引用,对象将如何被破坏?如上所述,您是否为 read_handle()提供了 shared_from_this()?

You are saying that manager_.dropSession(shared_from_this()); is being indirectly invoked from destructor. But how come object is being destructed, if read_handle() still keeps a reference it? Do you provide read_handle() with a shared_from_this() as I mentioned above?

这篇关于在销毁此对象所指向的对象之后,将调用shared_from_this():C ++ ASIO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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