简体   繁体   中英

“String iterator not dereferncable” with boost async_read_some

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM