Sockets 读取处理程序上释放的Boost绑定对象

Sockets 读取处理程序上释放的Boost绑定对象,sockets,boost-asio,boost-thread,Sockets,Boost Asio,Boost Thread,我使用Boost asio打开几个套接字,我使用一个集合,该集合带有指向自定义类的共享指针,其中包含所有套接字信息。这个类还有handle\u read函数,用于async\u receive,因为我需要对每个接收执行不同的操作,并且我不能绑定额外的参数 我遇到的问题是,当我关闭套接字时,我删除了对该指针的最后一个引用,因此在没有任何有效引用的情况下调用handle\u read函数,然后代码就中断了 void SocketsAPI::do_close(const SocketInfo sock

我使用Boost asio打开几个套接字,我使用一个集合,该集合带有指向自定义类的共享指针,其中包含所有套接字信息。这个类还有
handle\u read
函数,用于
async\u receive
,因为我需要对每个接收执行不同的操作,并且我不能绑定额外的参数

我遇到的问题是,当我关闭套接字时,我删除了对该指针的最后一个引用,因此在没有任何有效引用的情况下调用
handle\u read
函数,然后代码就中断了

void SocketsAPI::do_close(const SocketInfo socket)
{
    log("do_close");
    if (!socket.m_socket || !socket.m_socket->is_open()) {
        return;
    }   
    boost::system::error_code errorcode;
    socket.m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode);
    if (errorcode) {
        trace("Closing failed: ", errorcode.message());
    }
    socket.m_socket->close(errorcode);
    if (errorcode) {
        trace("Closing2 failed: ", errorcode.message());
    }
    mapType::iterator iter = sockets.find(socket.key);
    if (iter != sockets.end()) {
        sockets.erase (iter);
    }
    log("do_close end");
}

事实上,我不希望调用
handle\u read
函数,但我无法避免它,更糟糕的是,在多线程实现中(多个线程调用
io\u service.run()
),当关闭仍在处理时,将调用
handle\u read
,因此“this”对象将在处理程序的任何位置被释放。

听起来您很接近,但还没有完全理解通常使用Boost.Asio异步方法的应用程序的共享所有权语义。当处理程序执行异步操作时,您需要使用
shared\u from_this()
,以确保它们在异步操作期间保持在作用域内。
io\u服务::~io\u服务()
文档非常好

当您需要提前停止异步操作,而不是关闭
SocketsAPI::do_close()
方法中的套接字时。然后您的回调将得到一个错误代码,您可以使用该代码做出适当的反应


关闭操作仍在进行时,将调用
句柄\u read
已处理,因此“this”对象将在处理程序的任何位置被释放


这实际上是一个单独的问题,您需要使用
strand
s来处理回调函数中的数据结构。

感谢您提供的解决方案,这是我第一次使用Asio,似乎很难掌握。使用共享的\u from\u这在使用线程池时效果很好,但在仅使用1个线程时,我仍然会遇到崩溃,但这可能与原始问题无关。@frisco请随意问另一个问题问题问题是,我不确定问题是什么:D我得到了一个“微软C++异常:Booo::ExpExtIOFAX::CLNONIMPL在内存位置0x067 2F4BC……”但我不确定什么时候触发,VS调试也没有帮助。@ FRISCO如果你用这个问题来标记,我相信有人会帮助。