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

时间:2019-04-11 12:12:28

标签: c++ iphone clang one-definition-rule

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

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

libstatic1.a包含boost的某些版本,例如boost 1.x,而libdynamic1包含boost的另一个版本,例如boost1.y。现在将链接这两者的最终可执行文件是否违反ODR规则?

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

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

1 个答案:

答案 0 :(得分:1)

该标准仅讨论“程序”,其中“程序”是一组“链接在一起”的翻译单元,每个翻译单元由一系列声明[basic.link]组成。对于涉及动态库的问题,ODR也仅与“程序”有关,这并不那么直接。由于需要一个“程序”包含一个main函数[basic.start.main]/1,因此动态链接库通常不会单独符合“程序”的条件。

严格来说,我认为动态库只应被视为另一套翻译单元,它们与其余部分“链接”在一起形成最终程序。因此,只有将所有图像都加载到内存中并完成动态链接后,程序才能真正完成(运行时动态链接会使问题变得更加复杂,但是我猜这里可以忽略)。从这个意义上讲,您所描述的程序(将静态库和动态库链接在一起,每个库都使用不同版本的boost)几乎肯定会违反ODR,因为您将拥有多个翻译单元,例如,使用the same实体[basic.def.odr]/12的不同定义。

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