3

我有一个服务器,它使用来自 boost 的异步套接字和一个“接受”函数,如下所示(在这个例子中,“用户”几乎等同于“会话” ):

    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 的 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();
        }
    });
}

还有一个“写”功能。

当我将客户端连接到服务器时,从客户端到服务器的第一次传输顺利进行,服务器按预期发回响应。然后,我一步步往代码里走,read函数完成后,代码进入了几个我不认识的头文件,最终抛出“表达式:无法取消引用字符串迭代器,因为迭代器失效(例如发生了重新分配) , 或字符串被破坏)”xstring文件中的断言问题。对于我的一生,我不知道为什么。

编辑 1:buildReceivedMessage创建 a ReceivedMessage,其中以易于访问的格式包含请求的值,然后将其转发到 a 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");
    }
}
4

2 回答 2

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_ptrself来保持连接。这很好,但是否也buildReceivedMessage()创建了一个 shared_ptr self

handleSignin() 没有收到 shared_ptr,这让我怀疑你的对象self,也就是this,真的被过早地销毁了。

我会首先尝试使用self而不是thisin User::read(),以确保捕获self不会被优化掉(是的,这是可能的)。我还要确保不要仅仅依靠读取循环来保持连接处于活动状态。

于 2017-06-24T17:49:38.337 回答
-2

我遇到了类似的问题,ASIO 的一些读/写函数引用了您提供的可变缓冲区,并要求缓冲区在async函数完成之前是持久的。例如,使用字符串作为字符缓冲区传递asio::buffer(std::string("data"))将导致此断言,因为字符串在asio处理async函数时超出范围。也就是说,查看所有读/写函数并确保将字符串作为可变缓冲区传递到何处,该字符串是持久的。

于 2021-06-15T10:18:24.377 回答