I have a server that uses asynchronous sockets from boost with an "accept" function as follows ("User" is pretty much equivalent of "Session" in this example):
accept()
{
this->_acceptor.async_accept(this->_socket, [this](boost::system::error_code error)
{
if (!error)
{
make_shared<User>(move(_socket), *this)->read();
}
accept();
});
}
A "read" function as follows ( _readData
is a char array of 1024):
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();
}
});
}
And a "write" function.
When I connect with a client to the server, the first transmission from the client to the server goes smoothly, and the server sends back a response as expected. Then, I go step by step in the code, and after the read function finishes, the code goes into several header files I do not recognize, and eventually throws a "Expression: cannot dereference string iterator because the iterator was invalidated (eg reallocation occurred, or the string was destroyed)" assertion problem form the xstring
file. And for the life of me, I do not know why.
EDIT 1: The buildReceivedMessage
creates a ReceivedMessage
, which contains the values of the request in an easy-to-access format, and then forwards it to a messageHandler
, which forwards the request according to its type. For instance, the first request is a sign in request, so ReceivedMessage
ends up in this function:
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");
}
}
In:
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();
}
});
}
You are depending on shared_ptr self
to keep your connection alive. This is fine, but does buildReceivedMessage()
create a shared_ptr to self
as well?
handleSignin()
does not receive a shared_ptr, which makes me suspect that your object self
, which is this
, really is being destroyed prematurely.
I would first try to use self
instead of this
in User::read()
, to ensure the capture of self
doesn't get optimized away (yes, that is a possibility). I'd also make sure not to rely solely on the read loop to keep the connection alive.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.