【问题标题】:C++ standard library symbols bound at runtime to other librariesC++ 标准库符号在运行时绑定到其他库
【发布时间】:2020-07-21 04:42:54
【问题描述】:

我有一个在 RHEL 6 上使用 GCC 8.3 构建的 C++ 应用程序,并与一堆内部和外部共享库链接。

我试图了解加载器如何在运行时绑定我的应用程序符号。

我观察到但无法理解的是为什么 libstdc++.so 中的某些符号会映射到我的应用程序和共享库:

LD_DEBUG=bindings ldd -r main
[...]
binding file /usr/lib64/libstdc++.so.6 [0] to ./libshared01.so [0]: normal symbol `std::__detail::_Prime_rehash_policy::_M_next_bkt(unsigned long) const' [GLIBCXX_3.4.18]
binding file /usr/lib64/libstdc++.so.6 [0] to ./libshared02.so [0]: normal symbol `std::_Hash_bytes(void const*, unsigned long, unsigned long)' [CXXABI_1.3.5]
binding file /usr/lib64/libstdc++.so.6 [0] to ./libshared03.so [0]: normal symbol `char* std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_construct<__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<char> const&, std::forward_iterator_tag)' [GLIBCXX_3.4.14]
binding file /usr/lib64/libstdc++.so.6 [0] to ./libshared03.so [0]: normal symbol `char* std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag)' [GLIBCXX_3.4.14]
binding file /usr/lib64/libstdc++.so.6 [0] to ./libshared04.so [0]: normal symbol `std::__future_base::_Async_state_common::~_Async_state_common()' [GLIBCXX_3.4.17]
binding file /usr/lib64/libstdc++.so.6 [0] to ./main [0]: normal symbol `std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf()' [GLIBCXX_3.4]

并非所有标准符号都绑定在 libstdc++.so 之外,但只有少数,所有其他符号都按照我的预期进行映射:

binding file /usr/lib64/libstdc++.so.6 [0] to /usr/lib64/libstdc++.so.6 [0]: normal symbol `std::terminate()' [GLIBCXX_3.4]
binding file /usr/lib64/libstdc++.so.6 [0] to /usr/lib64/libstdc++.so.6 [0]: normal symbol `std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)' [GLIBCXX_3.4.9]
binding file /usr/lib64/libstdc++.so.6 [0] to /usr/lib64/libstdc++.so.6 [0]: normal symbol `std::basic_ostream<wchar_t, std::char_traits<wchar_t> >::sentry::~sentry()' [GLIBCXX_3.4]

我没有在我的代码中使用来自 GCC 的任何可见性标志或可见性属性。

但是我假设所有这些明确标识为标准符号的符号将默认映射到 libstdc++.so

我的根本问题是我的应用程序行为/性能似乎因此随机依赖于我无法控制的符号映射过程。如果我的一个外部依赖项被高度优化,并且我的应用程序的所有标准字符串符号突然从这个外部库中挑选出来,那感觉就像一个问题。

有人能解释一下这种行为吗?是否符合预期并记录在案?

【问题讨论】:

    标签: g++ runtime visibility loader libstdc++


    【解决方案1】:

    但是我假设所有这些明确标识为标准符号的符号将默认映射到 libstdc++.so。

    为什么?您正在查看的许多符号都是模板,并且在您构建时由编译器实例化。它们可能不存在于 libstdc++ 中。 [一些专业化,比如(比如)std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt;&gt;] 可能会在 dylib 中实例化以节省应用程序的空间;但肯定不是全部。

    您可以使用nm -g 获取从 libstdc++.so 导出的符号列表(如果我没记错的话)。 nm 的某些版本也有 -demangle 标志。您可能会对该列表的内容感到惊讶。

    【讨论】:

    • 我确实做了测试:nm -gDC --defined-only /usr/lib64/libstdc++.so.6 在构建过程中实例化的模板将存储在共享库中是有道理的。
    • 但是,我希望这些符号是“私有的”,并且在应用程序或其他库中不可见。在调查性能提升时,我注意到我的应用程序/库的一些模板化字符串符号被重新定位到另一个新优化的库。因此,即使没有实际使用新库,性能提升也是存在的。那么这可能是一个构建问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 2011-02-17
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    相关资源
    最近更新 更多