gpt4 book ai didi

c++ - shared_from_this() 在 this 指向的对象被销毁后调用 : C++ ASIO

转载 作者:行者123 更新时间:2023-11-28 02:32:36 25 4
gpt4 key购买 nike

我正在尝试开发 ASIO 应用程序并引用了 Chat-Server

当我的 CServer Object破坏它导致CSerSessionsManager Object破坏-持有shared pointer到所有事件的聊天 session 。它会导致所有事件 CSerCession Objects也要摧毁。

查看定义

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 Object破坏它导致read error用于事件 session 和 read_handle()被称为。

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

代码在 Exception Here. 处抛出异常。在调试时显示:

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 }

我可以看到 manager_.dropSession(shared_from_this());当调试器显示 std::enable_shared_from_this<channel::CSerSession> {_Wptr={[deleter and allocator]={_Uses=??? _Weaks=??? } 时被调用.

它在CSerSession object 销毁后被调用。作为read_error正在设置。错误的默认行为是销毁 session ,因此 manager_.dropSession(shared_from_this());那里是强制性的。

问题是 this object 的破坏导致 read_error再次尝试通过 manager_.dropSession(shared_from_this()); 销毁同一个对象

如何解决错误?

编辑:总结问题:

聊天 session 期间的任何错误都应设置 read errorread_handle()应该调用它然后通过 manager_.dropSession(shared_from_this()); 破坏聊天 session

但是当我的聊天 session CSerSession Object超出范围,即调用析构函数,它也会导致 read error因为它很活跃。再次manager_.dropSession(shared_from_this());正在被调用。

所以基本上 shared_from_this()正在从析构函数中间接调用。

最佳答案

当您从套接字读取并设置CSerSession::handle_read 读取处理程序时,您应该绑定(bind)shared_from_this() 而不是this

例如,您的 async_read() 应该与此类似:

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

您观察到的问题是由事件队列的性质引起的。当您销毁 CSerSession 时,事件队列中的某些事件可能会将 this 指针指向已销毁的对象。这就是开发人员推荐使用 shared_ptrshared_from_this() 的原因。当您传递 shared_ptr 而不是 this 时,您会保持感兴趣的对象存在。

对您的编辑的回应:

你是说 manager_.dropSession(shared_from_this()); 是从析构函数中间接调用的。但是,如果 read_handle() 仍然保留对它的引用,对象怎么会被破坏呢?您是否像我上面提到的那样为 read_handle() 提供了 shared_from_this()

关于c++ - shared_from_this() 在 this 指向的对象被销毁后调用 : C++ ASIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28544162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com