使用boost async_read_some“String iterator not dereferncable”

时间:2017-06-23 09:01:05

标签: c++ boost boost-asio shared-ptr asio

我有一个服务器使用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,其中包含易于访问格式的请求值,然后将其转发给messageHandlerReceivedMessage根据其类型转发请求。 例如,第一个请求是登录请求,因此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

2 个答案:

答案 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 函数时超出范围。也就是说,查看所有读/写函数并确保将字符串作为可变缓冲区传递的位置,该字符串是持久的。