链接静态和动态库时违反 ODR



链接静态 cpp 库和动态 cpp 库(都包含不同版本的 boost)会违反 ODR 吗?

我正在开发一个iPhone应用程序。对于最终的可执行文件,我需要链接一个静态库,比如libstatic1.a和一个动态框架,比如libdyanamic1。

libstatic1.a 包含某个版本的 boost,比如 boost 1.x,libdynamic1 包含另一个版本的 boost,比如 boost 1.y。现在链接这两个的最终可执行文件会违反 ODR 规则吗?

libdynamic1 中的符号可见性: 我使用nm -g -C libdynamic1检查了 libdynamic1 中存在的符号,并观察到 boost 线程池和 boost 文件系统的符号存在于列表中。

如果我违反了 ODR,我有哪些处理情况的选择? (到目前为止,我已经在多个设备上测试了可执行文件,并且没有遇到任何问题。

该标准只讨论"程序",其中"程序"是一组"链接在一起"的翻译单元,每个单元由一系列声明组成[basic.link]。当涉及到涉及动态库的问题时,争论ODR,它也只关注"程序",并不是那么简单。由于"程序"需要包含main函数 [basic.start.main]/1,因此动态链接库本身通常不符合"程序"的条件。

严格来说,我认为动态库必须被视为另一组翻译单元,这些翻译单元与其他单元"链接"以形成最终程序。因此,只有在所有图像都加载到内存中并且动态链接完成之后,程序才会真正完成(运行时动态链接似乎会使问题进一步复杂化,但我想可以忽略这里)。从这个意义上说,您的问题中描述的程序(链接静态和动态库,其中每个库都使用不同版本的 boost)几乎肯定会违反 ODR,因为您将有多个翻译单元,例如,使用相同实体的不同定义 [basic.def.odr]/12。

然而,在实践中,这个问题高度依赖于平台和工具链。在 ABI 级别,您通常会发现符号可以具有的链接类型比您在C++内的语言级别找到的链接类型更具差异性。例如,在 Windows 上,在构建动态库时,通常必须显式指定应导出哪些符号,默认情况下,所有名称都是库的内部名称。另一方面,在基于ELF的Linux上,情况并非如此。但是,您似乎可以使用-fvisibility=hidden选项将GCC切换到更类似于Windows的默认值,其中您的库将仅导出您明确告诉它的内容。请注意,您不得与库导出的界面中的 boost 有任何关系,因为这显然会导致在您的情况下出现未定义的行为......

相关内容

  • 没有找到相关文章

最新更新