我有一个服务器使用boost的异步套接字和“accept”函数,如下所示(“User”几乎等同于this示例中的“Session”):
accept()
{
this->_acceptor.async_accept(this->_socket, [this](boost::system::error_code error)
{
if (!error)
{
make_shared<User>(move(_socket), *this)->read();
}
accept();
});
}
“read”函数如下(_readData
是一个1024的char数组):
void User::read()
{
auto self(shared_from_this());
this->_socket.async_read_some(boost::asio::buffer(this->_readData, 1024),
[this, self](boost::system::error_code error, size_t length)
{
if (!error)
{
this->buildReceivedMessage(string(this->_readData, length));
this->read();
}
});
}
和“写”功能。
当我将客户端连接到服务器时,从客户端到服务器的第一次传输顺利进行,服务器按预期发回响应。然后,我逐步进入代码,在读取函数完成后,代码进入几个我无法识别的头文件,并最终抛出一个“表达式:无法取消引用字符串迭代器,因为迭代器无效(例如重新分配发生) ,或字符串被破坏)“断言问题形成xstring
文件。而对于我的生活,我不知道为什么。
编辑1:
buildReceivedMessage
创建ReceivedMessage
,其中包含易于访问格式的请求值,然后将其转发给messageHandler
,ReceivedMessage
根据其类型转发请求。
例如,第一个请求是登录请求,因此void User::handleSignin(shared_ptr<ReceivedMessage> msg)
{
vector<string> values = msg->getValues();
if (this->_server.getDB().isUserAndPassMatch(values[0], values[1]))
{
if (this->getUserByName(values[0]))
{
this->write("1022");
}
else
{
this->_server.addUser(shared_ptr<User>(this));
this->write("1020");
this->_username = values[0];
}
}
else
{
this->write("1021");
}
}
最终会出现在此函数中:
std::reduce
答案 0 :(得分:0)
在:
void User::read()
{
auto self(shared_from_this());
this->_socket.async_read_some(boost::asio::buffer(this->_readData, 1024),
[this, self](boost::system::error_code error, size_t length)
{
if (!error)
{
this->buildReceivedMessage(string(this->_readData, length));
this->read();
}
});
}
您依靠shared_ptr self
来保持您的连接活跃。这很好,但buildReceivedMessage()
也创建了一个shared_ptr到self
吗?
handleSignin()
没有收到shared_ptr,这让我怀疑您的self
对象this
确实正在被过早销毁。
我首先尝试在self
中使用this
代替User::read()
,以确保self
的捕获不会被优化掉(是的,这是一个可能性)。我还要确保不要仅仅依靠读取循环来保持连接的存在。
答案 1 :(得分:-2)
我遇到了类似的问题,ASIO 的一些读/写函数引用您提供的可变缓冲区,并要求缓冲区在 async
函数完成之前是持久的。使用字符串作为字符缓冲区,例如传递 asio::buffer(std::string("data"))
会导致此断言,因为字符串在 asio
处理 async
函数时超出范围。也就是说,查看所有读/写函数并确保将字符串作为可变缓冲区传递的位置,该字符串是持久的。