在销毁此对象所指向的对象之后,将调用shared_from_this():C ++ ASIO [英] shared_from_this() is called after object pointing by this is destroyed: 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屋!