链接 libboost_log.so 会使 boost::asio::io_service::运行立即退出

Linking libboost_log.so makes boost::asio::io_service::run exit immediately

本文关键字:运行 service 退出 io 链接 so log 会使 boost libboost asio      更新时间:2023-10-16

这是设置:

boost1::asio::io_service         _ios;
boost::asio::ip::tcp::acceptor  _acceptor;`
...
_acceptor(_ios)
...
boost::system::error_code ec;
int rc = _ios.run(ec);

使用 gdb,我看到运行调用跳转到 boost::asio::impl::io_service::运行
这里有一点提升

boost/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的证据。

Boost/Boost/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( 在我的二进制文件中提升::asio::d etail::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 中?这似乎是加速错误,不是吗?有没有办法确保预期的方法解析?

简而言之,Linux 上的运行时符号解析在符号可见性方面工作。如果符号在应用程序加载的一个或多个共享对象中在外部可见,则运行时链接器可以自由选择任何一个实现并在所有其他共享对象中使用它。这非常类似于编译时链接过程,它允许保留多个语言规则(例如,获取函数的地址必须产生相同的地址,无论该地址在程序中的哪个位置(。

Boost.Log确实使用Boost.ASIO来实现其某些功能(特别是基于网络的syslog sink(。Boost.ASIO 将其符号标记为外部可见,因此它们从 Boost.Log 共享对象导出。

现在,Boost.ASIO 不使用 ABI 命名空间或任何其他技术来根据库版本或配置使符号名称不同。这意味着任何使用 Boost.Log 和 Boost.ASIO 的应用程序或库都必须使用与构建 Boost.Log 时相同的 Boost.ASIO 版本,其配置方式与构建 Boost.Log 时配置的方式相同。否则,由于 ABI 不兼容,您可能会在您或 Boost.Log 对 Boost.ASIO 的使用中观察到各种未定义的行为。我怀疑这可能是您遇到问题的原因。

在构建代码和 Boost.Log 时,请检查您是否使用了相同版本的 Boost.ASIO。检查在这两种情况下是否以相同的方式定义所有宏。检查是否正在使用任何与 ABI 相关的编译器开关。