【发布时间】:2020-02-26 04:13:18
【问题描述】:
我在一个项目中使用两个独立的库(PLCIO 和 azure-iot-sdk-c)。这个项目主要是在 Windows 上使用 Visual Studio 开发的,但需要在 Linux 上运行。我目前正在使用 Ubuntu 机器来模拟生产。在 Windows 上的 Visual Studio 中编译程序时,出现链接器错误 LNK2005 和 LNK1169。我通过在 Visual Studio 中使用 /FORCE:MULTIPLE 链接器选项解决了这个问题。我们的应用程序在 Windows 上按预期编译和运行。
当我将代码和库移植到我的 Linux 测试盒时,我使用 cmake 来构建和链接所有内容。该项目可以正确构建和链接,但是当它运行时出现意外的分段错误。我通过一次使用一个库创建存根程序并确认它们按预期工作,将其缩小到两个库之间的交互。只有当我将两个库放在一起时,我才会遇到问题。我认为这是一个公平的假设,即相同的多重定义符号错误在 Linux 上导致了此段错误,只是由于某种原因在编译期间没有被捕获。
我已经尝试了一大堆编译和链接器标志(使用 GCC 和 Clang)来构建这个项目来尝试解决这个问题。我试过-fvisibility=hidden-shared-nostdlib。我在GCC documentation 中找到了-symbolic,但是当我尝试使用它时出现“无法识别的选项”错误。我最初是静态链接到预构建的库,但也尝试过动态链接以及使用我的其余代码自己构建 azure-iot-sdk。我每次都得到相同的结果。
基本上我的问题归结为,是否有任何相当于 /FORCE:MULTIPLE 的 Linux 工具链(GCC、Clang,我不在乎)可以解决这个问题。或者,我在数小时的谷歌搜索和故障排除中不知何故错过了一些替代解决方案?
【问题讨论】:
-
两个库中导出了哪些符号?将这两个库编译为静态(或共享)库并列出符号并进行比较。很可能
/FORCE:MULTIPLE选择了两个符号之一——只是gcc选择了错误的一个,但这两种方法都不好。使用objcopy重命名违规符号并针对重命名的符号进行开发。或者,也更简单,只需开发两个独立的进程,每个库一个,并进行进程间通信。 -
您应该显示代码。修复单一定义规则 (ODR) 违规可能比绕过它们更容易。绕过它们可能会导致难以诊断的模糊错误。
-
@jww 我无权访问代码,因为这是我链接到的两个预构建库。基于errors shown in Visual Studio,看起来
_get_time是有问题的符号,但我无法编辑这些库的源代码,也从未在自己的代码中直接引用此符号。 -
你能确认两个库都包含一个名为
get_time()的函数吗?您不需要在代码中调用它,只要从您的代码中调用的函数调用它就足够了。让链接器创建一个交叉引用以获得一些洞察力。 -
很遗憾,我无法确认这两个库都包含
get_time()。我对来自 azure-iot-sdk git repo 的源代码进行了 grep,可以找到对get_time()的引用,但不是定义。我没有其他图书馆的来源,所以我无法检查。我认为get_time()的唯一原因是有问题的功能是因为 Visual Studio 错误。
标签: c linux gcc linker symbols