如何使共享库符号强大?
Posted
技术标签:
【中文标题】如何使共享库符号强大?【英文标题】:How can I make a shared library's symbols strong? 【发布时间】:2016-12-07 21:06:38 【问题描述】:我创建了一个共享库,它引用了很多 C++ 模板函数。这些符号作为弱引用输入到共享库的导出表中(例如,当我使用 nm
查看共享库的符号时,它们显示为类型 W
)。这意味着在运行时,这些符号可能会被来自首先加载的不同共享库的副本插入。
我的共享库使用包含在库本身中的这些函数的副本,而不是来自任何其他库,这对我的应用程序很重要。有什么办法可以确保这一点?在我看来,这相当于将所有各种模板实例静态链接到共享库中。
【问题讨论】:
【参考方案1】:这意味着在运行时,这些符号可能会被插入 通过从首先加载的不同共享库中复制。
请注意,无论弱属性如何,它们都可以插入(请参阅this GCC post,它说动态链接器将弱点视为与强点类似,除非设置了LD_DYNAMIC_WEAK
,但通常不会设置)。
我的共享库对我的应用程序很重要 使用包含的这些功能的副本 在图书馆本身内,而不是来自任何其他图书馆。 有什么办法可以确保这一点?
您可以做几件事。
通常推荐的方法是将fvisibility=hidden
添加到您的CFLAGS 以防止从您的库中导出任何符号,然后用__attribute__((visibility("default")))
标记(希望很少)导出的函数。这也将允许在编译时进行更好的优化并加快启动速度,因为 rtld 将需要处理更少的符号。
穷人的有限解决方案是使用-fvisibility-inlines-hidden
,这是-fvisility=hidden
的有限形式。它只会隐藏内联函数(例如来自 STL 模板的函数)。
如果您不想弄乱源代码,请使用-Wl,-Bsymbolic
链接 - 这将强制尽可能在库中解析引用。
-- 编辑--
实际上,即使您启用 -fvisibility=hidden
以防止其他库(或可执行文件本身)动态插入库内对导出函数的引用,您也需要 -Bsymbolic
。
【讨论】:
谢谢。-Bsymbolic
和/或 -Bsymbolic-functions
是我的问题的解决方案。不过,我想我可能会采用推荐的方法来严格定义公共 API 并使用-fvisibility=hidden
。这似乎是最佳做法。
再想一想,我认为即使使用-fvisibility=hidden
,您也需要-Bsymbolic
- 没有它,导出的函数可以被其他共享库插入。此外,为了避免与fvisibility=hidden
混淆,您可以使用它更简单的变体-fvisiblity-inlines-hidden
- 这将隐藏所有内联函数(包括 STL 模板)。我已经更新了答案。以上是关于如何使共享库符号强大?的主要内容,如果未能解决你的问题,请参考以下文章