我在为链接错误而挣扎。我有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
实例的别名。通过查看链接到库B中的所有模块的符号来缩小范围,一旦确定了链接到库B中的模块,就需要找出原因。
您的问题没有提供足够的数据来决定性地识别链接问题,因为当然,这只能通过检查链接中涉及的所有对象模块,以及检查所有源代码中是否有可能违反“一个定义”规则,或者没有产生诊断结果,但表现为链接故障的格式错误的代码来完成。
因此,下面的答案旨在作为隔离这类链接故障的一般指南。我不认为这个问题有资格被规范的答案反复推敲。
链接的共享库中有一个符号在链接到可执行文件时无法解析,特别是:
ole::compound_document::find_storage(std::string const&)
就像在共享库上运行NM
一样,您可以在进入共享库的每个模块上单独使用它。这将查找未解析的引用来自哪个对象模块。如果您没有找到它,它一定来自您链接的静态库,所以在那里重复您的搜索。
该引用来自用于构建共享库的对象模块之一。你会发现它是这样的,它不太可能突然出现自己的存在。
找到相关模块后,您就可以自己动手了,查看编译的实际代码,并弄清楚发生了什么。如果你想不通:分而治之。取对象模块,并将源文件拆分成两个文件,每个文件中一半的函数,分别编译它们,然后看看未解析的引用来自哪里。
最后:在做所有这些之前,尝试一下低垂的果实:make clean
,然后重新编译所有内容。这具有编译器开关的所有特征,一些对象模块是由不同的编译器编译的。如果该静态库是由第三方供应商作为二进制blob提供的,那么它一定是由不同的编译器或不同版本的编译器编译的。C++不保证二进制ABI兼容性。