为什么旧编译器构建的某些库可以链接到现代代码,而其他库则不能?

我们有很多预构建的库(主要通过 CMake),使用 Visual Studio 2017 v141 构建。当我们尝试对使用 Visual STudio 2019 v142 的项目使用这些时,我们会看到如下错误:

错误 C1047 对象或库文件“boost_chrono-vc141-mt-gd-x32-1_68.lib”是由与其他对象不同版本的编译器创建的...

另一方面,我们还使用来自 3rd 方供应商的预编译 .libs,这些供应商已有十多年的历史,当与我们的代码库链接时,这些库工作得很好。

是什么决定了图书馆是否需要重建,为什么有些古老的图书馆还可以使用而其他只有一个版本的图书馆不能使用?

回答

ABI 不兼容可能会导致一些问题。尽管 C++ 标准要求对象如std::vectorandstd::mutex并且它们需要具有特定的公共/受保护成员,但如何创建这些类仍由实现决定。

在实践中,这意味着没有什么能阻止 GNU 标准库将其数据字段置于与 LLVM 标准库不同的顺序中,或者具有完全不同的私有成员。

因此,如果您尝试通过向其发送 GNU libstdc++ 向量来使用使用 LLVM libc++ 构建的库中的函数,则会导致 UB。即使在同一个标​​准库上,不同的版本也可能会改变一些东西,这可能是一个问题。

为了避免这些问题,流行的 C++ 库只在它们的 ABI 中使用 C 数据结构,因为(至少现在)每个编译器为 char*、int 或 struct 生成相同的内存布局。

这些 ABI 问题可能出现在两个地方:

  • 当您使用动态库(.so 和 .dll 文件)时,您的编译器可能不会说什么,并且当您使用不兼容的 C++ 对象调用库的函数时,您将获得未定义的行为。
  • 当您使用静态库(.a 和 .lib 文件)时,我不太确定,我猜它可能会在发现问题时打印错误,或者成功编译一些会表现的二进制文件的科学怪人怪物像上面的点

以上是为什么旧编译器构建的某些库可以链接到现代代码,而其他库则不能?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>