我有一个做async_read_some的boost插座:

socket_.async_read_some(boost::asio::buffer(data_, max_length),
    boost::bind(&Session::handle_read, this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred));


删除我的Session类时,将调用socket_.close()。我以为这会取消async_read_some并以错误方式调用Session::handle_read

但是,情况并非如此,请看basic_socket.hpp

/// Close the socket.
/**
* This function is used to close the socket. Any asynchronous send, receive
* or connect operations will be cancelled immediately, and will complete
* with the boost::asio::error::operation_aborted error.
*
* @throws boost::system::system_error Thrown on failure. Note that, even if
* the function indicates an error, the underlying descriptor is closed.
*
* @note For portable behaviour with respect to graceful closure of a
* connected socket, call shutdown() before closing the socket.
*/
void close()


没有提及读取被取消。所以我的问题是,如何取消读取,以便可以干净地关闭套接字?

最佳答案

首先,假定run仍处于有效状态,这将导致在调用下一个run_onepollpoll_oneio_service时调用该句柄。取消/关闭不会突然改变在ASIO中调用处理程序的行为。

因此,如果在删除Session时触发此操作,则将拥有UB,因为处理程序将在销毁的对象上调用,因为您将原始指针传递给了它,该指针随后已被删除。

我通常的技术是将shared_ptr与pimpl模式的变体结合使用。我通常在共享指针中实现该实现,并将其传递给各种ASIO调用。当外部接口被破坏时,我在pimpl上调用了shutdown方法,这导致ASIO取消其操作,然后接口重置其共享指针的副本。

一旦ASIO调用了存储的处理程序,它将不再具有共享指针的副本,并且销毁将完成。

07-26 09:28
查看更多