在io_service :: stop()之后,在io_service :: ~io_service()中调用boost :: asio - asio_handler_deallocate

时间:2011-11-04 17:54:09

标签: c++ boost boost-asio

我使用ip::udp::socket构建了io_service。只有一个boost::thread调用io_service::run()方法,而io_service::work实例则阻止io_service::run()返回。我的ip::udp::socket的完成处理程序具有自定义asio_handler_allocate()asio_handler_deallocate()函数,这些函数由my::custom_memory_pool支持。

当我的应用程序退出时,我的关闭线程会发生这一系列事件:

  1. ip::udp::socket::close()
  2. work::~work()
  3. io_service::stop()
  4. thread::join()
  5. my::custom_memory_pool::~custom_memory_pool()
  6. ip::udp::socket::~socket()
  7. thread::~thread()
  8. io_service::~io_service()
  9. 在第8步中,对io_service::~io_service()的调用会导致......

    Program terminated with signal 11, Segmentation fault.
    #0  0x00000000005ad93c in my::custom_memory_pool<boost::aligned_storage<512u, -1u> >::deallocate (this=0x36323f8, t=0x7fca97a07880)
        at memory.hpp:82
    82                      reinterpret_cast<pool_node*>(t)->next_ = head_;
    (gdb) bt 30
    #0  0x00000000005ad93c in my::custom_memory_pool<boost::aligned_storage<512u, -1u> >::deallocate (this=0x36323f8, t=0x7fca97a07880)
        at memory.hpp:82
    #1  0x00000000005ad40a in asio_handler_deallocate (p=0x7fca97a07880, s=96, h=0x7fffe09d5480) at net.cpp:22
    #2  0x0000000000571a07 in boost_asio_handler_alloc_helpers::deallocate<socket_multicast::completion_handler> (p=0x7fca97a07880, s=96, h=...)
        at /usr/include/boost/asio/detail/handler_alloc_helpers.hpp:51
    #3  0x0000000000558256 in boost::asio::detail::reactive_socket_recvfrom_op<boost::asio::mutable_buffers_1, boost::asio::ip::basic_endpoint<boost::asio::ip::udp>, socket_multicast::completion_handler>::ptr::reset (this=0x7fffe09d54b0)
        at /usr/include/boost/asio/detail/reactive_socket_recvfrom_op.hpp:81
    #4  0x0000000000558310 in boost::asio::detail::reactive_socket_recvfrom_op<boost::asio::mutable_buffers_1, boost::asio::ip::basic_endpoint<boost::asio::ip::udp>, socket_multicast::completion_handler>::do_complete (owner=0x0, base=0x7fca97a07880)
        at /usr/include/boost/asio/detail/reactive_socket_recvfrom_op.hpp:112
    #5  0x0000000000426706 in boost::asio::detail::task_io_service_operation::destroy (this=0x7fca97a07880)
        at /usr/include/boost/asio/detail/task_io_service_operation.hpp:41
    #6  0x000000000042841b in boost::asio::detail::task_io_service::shutdown_service (this=0xd4df30)
        at /usr/include/boost/asio/detail/impl/task_io_service.ipp:96
    #7  0x0000000000426388 in boost::asio::detail::service_registry::~service_registry (this=0xd4a320, __in_chrg=<value optimized out>)
        at /usr/include/boost/asio/detail/impl/service_registry.ipp:43
    #8  0x0000000000428e99 in boost::asio::io_service::~io_service (this=0xd49f38, __in_chrg=<value optimized out>)
        at /usr/include/boost/asio/impl/io_service.ipp:51
    

    所以io_service::~io_service()试图将一些内存释放到我在第5步中销毁的池中。

    我无法将my::custom_memory_pool::~custom_memory_pool()移到io_service::~io_service()之后。

    我预计在io_service::stop()thread::join()返回后,可能不再有asio_handler_deallocate()次来电。显然情况并非如此。我可以在步骤3中强制io_service使所有完成事件出列并释放所有处理程序内存,以及如何在io_service完成这些任务之前阻塞?

2 个答案:

答案 0 :(得分:4)

以下是答案:在拆除io_service及其服务时,请勿致电io_service::stop()。只需work::~work()

io_service::stop()实际上仅用于暂时暂停io_service,以便以后可能io_service::reset()io_service的普通正常关闭不应涉及io_service::stop()

答案 1 :(得分:1)

调用io_service::stop()不允许它完成任何处理程序,它只是在任何当前正在运行的处理程序之后停止处理并尽快返回。

由于在销毁io_service时各种内部结构被破坏,因此一种解决方案是控制相对于自定义分配器销毁io_service的顺序。如果它们位于相同的结构中(在结构中的io_service之前具有分配器),则可以正确地对它们进行排序,或者使用堆并明确地命令它们的销毁以保证io_service首先被销毁。