【问题标题】:Why are std:: symbols forcibly exported in shared libraries?为什么 std:: 符号在共享库中被强制导出?
【发布时间】:2020-02-08 02:10:49
【问题描述】:

如果您的共享库在内部使用 C++,那么它所引用的所有 std:: 模板和类型将被导出为弱符号。即使您使用-fvisiblity=hidden-Wl,--exclude-libs,ALL。隐藏这些符号的唯一方法是使用版本脚本。

这些强制出口的目的是什么?

用版本脚本隐藏它们有什么害处吗?

【问题讨论】:

    标签: c++ linux gcc linker shared-libraries


    【解决方案1】:

    所以我发现了两个(被拒绝的)GCC-bugreports 讨论这个问题:

    推理似乎是:

    • 使用 stl 时沿库边界更容易编程
    • 更简单的 stl 测试
    • 总体而言,很难始终如一地隐藏模板实现细节

    尤其是this comment by Benjamin Kosnik。出于保存目的引用:

    这不是错误,而是有意的链接策略的一部分。

    对于 C++,要跨共享库使用的类型必须是 可见的。见:

    http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options

    特别是:

    请注意,“-fvisibility”确实会影响 C++ 模糊链接实体。这 意味着,例如,将抛出一个异常类 DSO 之间必须明确标记为默认可见性,以便 'type_info' 节点将在 DSO 之间统一。

    因此,libstdc++ 具有命名空间 std 的基本原理具有可见性 “默认。”如果您要破解对允许命名空间 std 的支持 具有隐藏的可见性,并运行测试套件 -fvisibility=hidden (见附加补丁)你会注意到测试结果的崩溃,大量失败。因此,它提供给 仅供参考。

    在 libstdc++ 源文件中,匿名命名空间用于 具有本地/隐藏链接的特定实体。这种使用 匿名命名空间被认为优于隐藏的属性,因为它 使用 ISO C++,因此比供应商扩展更可移植(pragmas 或属性)。

    但是,在 libstdc++ 头文件中,属性 hidden 已经 难以使用。有人可能会认为,也许所有的实现 details 可以移动到说 std::__detail,然后用 属性隐藏。然后,许多这些辅助函数将被标记 正如您在下面的示例中所隐藏的那样。

    这种方法存在一些缺陷:

    1. 默认使用的所有这些实现基类型 派生类必须是默认的
    2. 与实现相同 使用静态局部变量的详细信息
    3. 与虚函数等相同 等
    4. 因此你最终得到的隐藏的东西非常有限

    另外,这可能会加剧 dlopen + RTLD_LOCAL + 弱符号 C++ 的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-30
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多