【问题标题】:Can multiple shared libaries used by a program use different static linked libc?一个程序使用的多个共享库可以使用不同的静态链接libc吗?
【发布时间】:2021-07-03 22:37:27
【问题描述】:

在 Windows 上可以这样做(虽然不推荐,因为在不同的 c 库实例之间传递 c 标准库对象可能会出现问题),例如 this:

每个可执行映像(EXE 或 DLL)都可以有自己的静态链接 CRT,也可以动态链接到 CRT。特定图像中静态包含或动态加载的 CRT 版本取决于构建它的工具和库的版本。单个进程可以加载多个 EXE 和 DLL 映像,每个映像都有自己的 CRT

这可以在 Linux 上完成吗?

this 是否意味着错误?但是像Linux这样的通用系统应该没有这样的限制吧?例如,如果代码库 A 和代码库 B 确实需要不同版本的 libc 才能正常工作,并且假设它们都有非常简单的 C 风格 API 供客户端使用(即这些 API 中没有指针参数)怎么办?

如果不可能,则无需阅读以下内容。

作为实现这一目标的第一步,当我尝试使用静态链接 libc 构建共享库时:

 g++ -fPIC -Wall -fexceptions -g  -c main.cpp -o main.o
 g++ -shared -static  main.o  -o libtestCppSharedLib.so
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

【问题讨论】:

  • 静态链接的库包含在生成的二进制文件中,因此两个静态链接到不同库的二进制文件没有问题。有趣的是(当您链接时)这样的静态链接库具有对动态库的引用。 AFAIK 此类引用包括动态库的版本号,以便满足所需的接口。 Linux 系统上可以存在多个版本的动态库。
  • @thebusybee 但是这里考虑的库是一个非常特殊的库:libc。 libc 与加载/初始化/系统调用过程有关系,所以 libc 的问题可能不是小事
  • 当然,但是如果存在多个版本的 libc 并在特定系统上运行,为什么引用它们的应用程序不能运行?例如,如果应用程序引用了较新版本的 libc,而静态链接库引用了较旧版本的 libc?
  • 我可以想到一些特殊情况,需要应用程序和静态链接库进行特定的系统调用序列,这可能不起作用,因为不同的引用版本的 libc 不兼容。在这种情况下,我认为您需要将应用程序动态链接到库引用的 libc。
  • 请说明您为什么要这样做。这与所有常见的 Linux 做法背道而驰。阅读 Drepper 的论文How to write shared libraries

标签: c static-linking dynamic-linking libc crt


【解决方案1】:

这可以在 Linux 上完成吗?

理论上:是的。在实践中:没有。

Linux 上可用的libc 版本均不支持在单个进程中拥有多个库副本。

此外,与 Windows DLL 相比,UNIX 和 Linux 使用非常不同的链接模型。

在 Windows 下,DLL 是一个自包含的单元——只有从它显式导出的函数和变量从外部可见,并且调用 DLL 中定义的函数将总是导致调用它函数(无符号插入)。

在 UNIX 模型下,默认情况下导出共享库中的所有内容,调用同一库中定义的函数在运行时可能会或可能不会解析为该函数。

如果代码库 A 和代码库 B 真的需要不同版本的 libc 才能正常工作,该怎么办?

libc 提供了一个标准 接口。如果A 需要libc特定 版本才能正常工作,那么它就坏了。 UNIX 理念是您应该修复 AB(或两者)。

【讨论】:

  • 结论可能是真的,我稍后会验证,但推理可能存在一些问题: (1) "None of libc ..." 通常不需要将库设计为可以工作以这种方式以这种方式工作,他们在大多数情况下只是以这种方式工作。它们只分解一些特殊情况——但 gcc 的特殊情况是什么——它们存在吗?
  • (2)“在UNIX模型下,共享库中的所有内容都被导出”,可见性标志和属性可以解决问题,对于静态链接的libc,libc实例只服务于客户端它链接到的共享库不会导出符号,并且具有静态链接 libc 的共享库中的客户端将使用该 libc,这些客户端没有动态链接问题。而没有 libc 的主可执行文件和共享库中的客户端将使用带有动态链接的共享版本的 libc。
猜你喜欢
  • 1970-01-01
  • 2012-07-29
  • 2011-01-25
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
  • 2021-12-14
  • 1970-01-01
相关资源
最近更新 更多