【发布时间】:2020-02-08 02:10:49
【问题描述】:
如果您的共享库在内部使用 C++,那么它所引用的所有 std:: 模板和类型将被导出为弱符号。即使您使用-fvisiblity=hidden 和-Wl,--exclude-libs,ALL。隐藏这些符号的唯一方法是使用版本脚本。
这些强制出口的目的是什么?
用版本脚本隐藏它们有什么害处吗?
【问题讨论】:
标签: c++ linux gcc linker shared-libraries
如果您的共享库在内部使用 C++,那么它所引用的所有 std:: 模板和类型将被导出为弱符号。即使您使用-fvisiblity=hidden 和-Wl,--exclude-libs,ALL。隐藏这些符号的唯一方法是使用版本脚本。
这些强制出口的目的是什么?
用版本脚本隐藏它们有什么害处吗?
【问题讨论】:
标签: c++ linux gcc linker shared-libraries
所以我发现了两个(被拒绝的)GCC-bugreports 讨论这个问题:
推理似乎是:
尤其是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,然后用 属性隐藏。然后,许多这些辅助函数将被标记 正如您在下面的示例中所隐藏的那样。
这种方法存在一些缺陷:
- 默认使用的所有这些实现基类型 派生类必须是默认的
- 与实现相同 使用静态局部变量的详细信息
- 与虚函数等相同 等
- 因此你最终得到的隐藏的东西非常有限
另外,这可能会加剧 dlopen + RTLD_LOCAL + 弱符号 C++ 的问题。
【讨论】: