以下是设置:
boost1::asio::io_service _ios;
boost::asio::ip::tcp::acceptor _acceptor;`
...
_acceptor(_ios)
...
boost::system::error_code ec;
int rc = _ios.run(ec);
使用gdb我看到run run跳转到boost :: asio :: impl :: io_service :: run
这里有一点提升
升压/ ASIO / IMPL / io_service.ipp:
std::size_t io_service::run(boost::system::error_code& ec)
{
return impl_.run(ec);
}
这是证明impl_是linux案例的task_io_service。
升压/升压/ ASIO / io_service.hpp
#if defined(BOOST_ASIO_HAS_IOCP)
namespace detail { typedef win_iocp_io_service io_service_impl; }
#else
namespace detail { typedef task_io_service io_service_impl; }
#endif
...
private:
typedef detail::io_service_impl impl_type;
#if defined(BOOST_ASIO_HAS_IOCP)
friend class detail::win_iocp_overlapped_ptr;
#endif
...
impl_type& impl_;
如果我在编译期间没有链接-lboost_log,则解析impl_run调用(通过plt存根调用,ld_trampoline.S dl-runtime_resolve和dl-runtime.c _dl_fixup)来boost :: asio :: detail: :impl :: task_io_service ::在我的二进制文件中运行,run()开始等待接受者提供的工作。
如果我通过GDB进行链接提升,我会看到此调用被解析为libboost_log.so符号_ZN5boost4asio6detail15task_io_service3runERNS_6system10error_codeE并且几乎立即退出。
nm -D libboost_log.so确认符号在那里,这不是我的链接问题。
为什么这个task_io_service3run符号在libboost_log.so中?这似乎是助推器,不是吗?有没有办法确保预期的方法解决方案?
答案 0 :(得分:0)
简而言之,Linux上的运行时符号解析符合符号可见性。如果符号在一个或多个随应用程序加载的共享对象中是外部可见的,则运行时链接程序可以自由选择任何一个实现并在所有其他共享对象中使用它。这非常类似于编译时链接过程,它允许保存多个语言规则(例如,获取函数的地址必须产生相同的地址,无论在程序中的哪个地址都采用)。
Boost.Log确实使用Boost.ASIO来实现它的一些功能(特别是基于网络的syslog接收器)。 Boost.ASIO将其符号标记为外部可见,因此它们从Boost.Log共享对象中导出。
现在,Boost.ASIO不使用ABI命名空间或任何其他技术来根据库版本或配置使符号名称不同。这意味着使用Boost.Log和Boost.ASIO的任何应用程序或库必须使用相同版本的Boost.ASIO,其配置方式与构建Boost.Log时配置的方式相同。否则,由于ABI不兼容,您可能会在Boost.Log使用Boost.ASIO时观察到各种未定义的行为。我怀疑这可能是你遇到问题的原因。
在构建代码和Boost.Log时,请检查您是否使用了相同版本的Boost.ASIO。在两种情况下检查所有宏的定义方式是否相同。检查您是否使用任何与ABI相关的编译器开关。