如何解决链接到静态库的共享库中的 C++ 链接错误

How to solve C++ linking error in shared library linked to a static library

我遇到了链接错误。 我有 3 个模块:

在可执行文件 C 的链接过程中,我收到以下错误消息:

../../bin/B.so: undefined reference to `ole::compound_document::find_storage(std::string const&)'

函数在库A中定义。 如果我在共享库 B 上 运行 实用程序 nm,我会收到以下输出:

0000000001841c70 T ole::compound_document::find_storage(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
                 U ole::compound_document::find_storage(std::string const&)

它显示了两个 find_storage 函数。其中一个已定义,另一个未定义。 我试图了解它是如何发生的。至今未成功。 问题出现在Linux(Ubuntu)下,编译器:clang-9。在 Windows,我可以毫无问题地构建库和可执行文件。

我试图创建一个最小的示例,只是将 3 个简单的模块与几个函数放在一起。一切正常。编译器只使用函数的第一个定义。我不明白第二个定义从何而来。我怀疑是 c++ 标准的混合,但找不到任何东西。

任何建议将不胜感激。

您需要在库 B 的代码中查找问题。 std::string,一字不差,不是预期从导出符号引用的实际类型,因为 std::string 只是 std::basic_string 实例的别名。通过查看 link 编辑到库 B 中的所有模块的符号来缩小范围,一旦你确定了这样做的模块,你就需要找出原因。

你的问题没有提供足够的数据来决定性地识别 linking 问题,因为当然,这只能通过检查 linking 中涉及的所有对象模块来完成,并且检查所有源代码是否可能违反单一定义规则,或未产生诊断但表现为 link 故障的格式错误的代码。

因此,以下答案旨在作为隔离此类 linking 故障的一般指南。我认为这个问题不符合规范答案的标准。

您在 linked 共享库中有一个符号在 linked 到可执行文件时没有得到解析,特别是:

ole::compound_document::find_storage(std::string const&)

就像您在共享库上 运行 nm 一样,您可以在进入共享库的每个模块上单独使用它。这将找到未解析的引用来自哪个对象模块。如果您没有找到它,它一定来自您 link 编辑的静态库,因此请在那里重复搜索。

该引用来自您用来构建共享库的目标模块之一。你会这样找到它,它不太可能突然出现。

找到相关模块后,您就可以靠自己了,通过查看编译的实际代码,找出发生了什么。如果你想不通:分而治之。拿目标模块,将源文件拆分成两个文件,每个文件一半的函数,分别编译,然后查看未解析的引用来自哪里。

最后:在做所有这些之前,先尝试一下容易实现的结果:make clean,然后重新编译所有内容。这具有编译器开关的所有特征,一些目标模块是由不同的编译器编译的。如果该静态库是由第三方供应商作为二进制 blob 提供的,则它一定是由不同的编译器或不同版本的编译器编译的。 C++ 不保证 运行tee 二进制 ABI 兼容性。

正如 n. 'pronouns' m. 所提到的,问题在于 -D_GLIBCXX_USE_CXX11_ABI 标志的使用不一致。我使用的是 c++14 标准,但有些项目是用标志 -D_GLIBCXX_USE_CXX11_ABI=1 编译的。 发现起来并不容易,因为我在 conan 包管理器中使用了很多第 3 方库。