У меня есть сервер, который использует асинхронные сокеты от boost с функцией «accept» следующим образом («User» в значительной степени эквивалентен «Session» в этот пример):
accept()
{
this->_acceptor.async_accept(this->_socket, [this](boost::system::error_code error)
{
if (!error)
{
make_shared<User>(move(_socket), *this)->read();
}
accept();
});
}
Функция «читать» следующим образом (_readData
это массив символов 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();
}
});
}
И функция записи.
Когда я соединяюсь с клиентом к серверу, первая передача от клиента к серверу проходит гладко, и сервер отправляет ответ, как и ожидалось. Затем я пошагово выполняю код, и после завершения функции чтения код переходит в несколько файлов заголовков, которые я не распознаю, и в конечном итоге выдает «Выражение: невозможно разыменовать строковый итератор, потому что итератор признан недействительным (например, произошло перераспределение»). или строка была уничтожена) 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");
}
}
В:
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
не оптимизируется (да, это возможно). Я бы также позаботился о том, чтобы не полагаться исключительно на цикл чтения для поддержания связи.
Других решений пока нет …