C++ Asio:异步操作超时

C++ Asio:异步操作超时,c++,asynchronous,boost,segmentation-fault,boost-asio,C++,Asynchronous,Boost,Segmentation Fault,Boost Asio,我的程序充当客户端可以连接的服务器。一旦客户机连接,他将每隔~5秒从服务器获得更新。这是每5秒调用一次的写入函数,用于将新数据发送到客户端: void NIUserSession::write(std::string &message_orig) { std::cout << "Writing message" << std::endl; std::shared_ptr<std::string> message = std::make

我的程序充当客户端可以连接的服务器。一旦客户机连接,他将每隔~5秒从服务器获得更新。这是每5秒调用一次的写入函数,用于将新数据发送到客户端:

void NIUserSession::write(std::string &message_orig)
{
    std::cout << "Writing message" << std::endl;

    std::shared_ptr<std::string> message = std::make_shared<std::string>( message_orig );
    message->append("<EOF>");
    boost::system::error_code ec;
    boost::asio::async_write(this->socket_, boost::asio::buffer(*message),
        boost::asio::transfer_all(), boost::bind(&NIUserSession::writeHandler,
               this, boost::asio::placeholders::error,
               boost::asio::placeholders::bytes_transferred(),
               message 
               ));
}

void NIUserSession::writeHandler(const boost::system::error_code &error, std::size_t bytes_transferred, std::shared_ptr<std::string> message)
{
    std::cout << "Write Handler" << std::endl;
    if(error)
    {
        std::cout << "Write handler error: " << error.message() << std::endl;
        this->disconnect();
    }
}

void NIUserSession::disconnect()
{
    std::cout << "Disconnecting client, cancling all write and read operations." << std::endl;
    this->socket_.lowest_layer().cancel();

    delete this;
}
如果连接超时,则会发生以下情况:

Writing message
Write Handler
Write handler error: Connection timed out
Disconnecting client, cancling all write and read operations.
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Segmentation fault
最后,出现分段错误。我认为这是因为disconnects在其他异步操作仍在进行时被调用。 我想我可以通过使用这个->socket\u.lower\u layer.cancel;直接在第一个异步操作失败之后,但它不工作


如何避免分段错误?

嗯,取消操作时不应删除此错误,因为挂起的I/O操作的回调仍将被调用,然后访问此错误会导致未定义的行为。有多种方法可以解决此问题:

在实际知道以前的数据已经写入之前,不要写入数据。您可以将传递给NIUserSession::write的std::string实例排队,以防未完成的写入操作仍处于挂起状态,然后在未完成的写入操作完成时在处理程序中实际写入它们。这样,您就不会有多个I/O操作在运行中。 从std继承::从\u this启用\u shared\u,并从\u this(而不是此)将shared\u传递给异步\u write调用这就是所做的。这样,挂起的I/O操作将保留对类的引用,如果所有操作都完成,则将调用析构函数。
这不会导致分割错误。它导致了一场灾难。否则,+1在使用异步操作时,您需要非常小心对象的生存期。boost::asio使用shared_ptr有很好的理由,请参阅:@sehe-谢谢,编辑:我的不好,因为使用了不正确的措辞。谢谢,我将很快检查并回复:
Writing message
Write Handler
Write handler error: Connection timed out
Disconnecting client, cancling all write and read operations.
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Write Handler
Segmentation fault