我使用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
支持。
当我的应用程序退出时,我的关闭线程会发生这一系列事件:
ip::udp::socket::close()
work::~work()
io_service::stop()
thread::join()
my::custom_memory_pool::~custom_memory_pool()
ip::udp::socket::~socket()
thread::~thread()
io_service::~io_service()
在第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
完成这些任务之前阻塞?
答案 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
首先被销毁。