c++ - 为什么不鼓励静态链接 glibc?
问题描述
大多数在线资料表明您可以静态链接 glibc,但不鼓励这样做;例如centos 软件包回购:
glibc-static 包包含用于 -static 链接的 C 库静态库。你不需要这些,除非你静态链接,这是非常不鼓励的。
这些消息来源很少(或从不)说明为什么这是一个坏主意。
解决方案
其他答案中给出的原因是正确的,但它们不是最重要的原因。
glibc 不应该被静态链接的最重要原因是它在内部广泛使用dlopen
, 来加载 NSS(名称服务切换)模块和iconv
转换。模块本身引用 C 库函数。如果主程序与 C 库动态链接,那没问题。但是如果主程序与 C 库静态链接,dlopen
则必须去加载 C 库的第二个副本以满足模块的加载要求。
这意味着您的“静态链接”程序仍然需要在文件系统上存在副本libc.so.6
,加上 NSS 或iconv
任何模块本身,以及模块可能需要的其他动态库,例如ld-linux.so.2
,libresolv.so.2
等。这不是人们想要的当他们静态链接程序时通常需要。
这也意味着静态链接的程序在其地址空间中有两个 C 库副本,它们可能会为使用谁的stdout
缓冲区、谁可以使用sbrk
非零参数调用,诸如此类的事情发生争执。glibc 内部有一堆防御性逻辑试图使这项工作发挥作用,但从未保证它会工作。
您可能认为您的程序不需要担心这一点,因为它从不调用getaddrinfo
or iconv
,但语言环境支持iconv
在内部使用,这意味着任何stdio.h
函数都可能触发对 的调用dlopen
,并且您无法控制用户的环境变量设置做。
例如,如果您的程序确实调用iconv
了 ,那么情况会变得更糟,尤其是当“静态链接”可执行文件构建在一个发行版上,然后复制到另一个发行版时。这些iconv
模块有时位于不同发行版的不同位置,因此在 Red Hat 发行版上构建的可执行文件可能无法在 Debian 上正常运行,这与人们对静态链接可执行文件的期望完全相反。
推荐阅读
- c++ - Qt 动作不会连接到插槽
- java - Maven 阴影插件替换 persistence.xml
- javascript - 单击模态同意按钮时未选中复选框
- php - 如何检查字符串是否不存在然后返回 false?
- apache-kafka - 如何使用 kafka-python 获取 kafka 主题的分区?
- c - 当我尝试使用 struct 运行程序时出现分段错误(核心转储)
- c# - C# Compile OutOfMemory 错误,而我正在尝试动态生成要编译的文件操作代码
- clojure - Clojure - 使用 Cloud Firestore 获取实时更新
- python - 在字符串列表中搜索的高效且最快的方法
- c# - 将多个流序列化为一个流