主要是历史原因吗?是不是还有其他的理由?
1
ysc3839 2019-01-13 18:36:01 +08:00 via Android 1
足够不代表可以随意浪费,当节约的成本几乎为 0 的时候为什么还要浪费?
|
2
doun 2019-01-13 18:37:24 +08:00 via iPhone
版本管理等,编译时间等? golang 不就是全静态编译链接了吗
|
3
Osk 2019-01-13 18:40:01 +08:00 2
想起了被 node_modules 支配的恐惧,,,
|
4
across 2019-01-13 18:41:50 +08:00
为什么不用 shared lib,反而要采用浪费内存和磁盘的方法?
|
5
thedrwu 2019-01-13 18:41:51 +08:00 via Android
底层库的 hotfix/upgrade 不会牵一发而动全身
Windows hook LGPL obj/linker 的兼容性 等等 |
6
fhc023 OP 哦 我是觉得相对它的收益 成本有点高。作为库的使用者,得保证开发和生产环境的这些依赖版本都一致。还是很痛苦的。
|
7
wbing 2019-01-13 18:43:11 +08:00
改一个库的功能,把库替换了就好了,就不用把使用这个库的程序再重新编译一次
|
8
justou 2019-01-13 18:43:31 +08:00 5
|
10
shyangs 2019-01-13 18:44:44 +08:00
想起了被 node_modules 支配的恐惧
::doge:: |
13
thedrwu 2019-01-13 18:54:06 +08:00 via Android
@fhc023 如果操作系统的 runtime 打个补丁,需要重新安装所有的程序。还是说每个程序都静态链接一份操作系统?
|
14
tewilove 2019-01-13 19:00:28 +08:00 via Android
库克:mmp。
安卓:内存可能只够开个 QQ。 |
15
WordTian 2019-01-13 19:07:40 +08:00 via Android
并不够,比如 office 软件要都搞成静态链接,开了这个你就不用干别的了
|
16
catalina 2019-01-13 20:31:24 +08:00
别开玩笑,你想折腾死那些官方源和镜像源吗(笑哭)
|
18
fhc023 OP 我二了
|
19
misaka19000 2019-01-13 20:45:20 +08:00 1
我觉得对于客户端程序动态链接是有必要的,而对于服务端的程序则比较适合使用静态链接的程序
|
20
danc 2019-01-13 20:58:53 +08:00
开玩笑吧。比如 windows 操作系统,你看有多少 dll 文件,你要静态链接了,编译一次得多久,而且你的内存能放得下不
|
21
byteli 2019-01-13 21:14:21 +08:00 via Android
很多是为了热更的
|
22
expy 2019-01-13 21:30:58 +08:00
作为用户还是喜欢普通应用层软件静态链接,下一个可执行文件到处都能跑。
|
23
smdbh 2019-01-13 21:31:00 +08:00
1. 并不够
2. 修改维护 |
24
yanqiyu 2019-01-13 21:39:09 +08:00 1
glibc:我现在要修一个 BUG,请问你准备更新几个软件呢
|
25
fhc023 OP 仔细想了下。像底层库更新这种情况的话,用动态库确实可以不用让依赖它的库重新打包。如果接口和行为没有改变的话是很不错的,但是也是可能带来兼容性问题。比如,底层库做了个 breaking change,那后续的库如果不改动的话也不能跑了。目前这种情况主要是包管理器来做依赖检查,然后决定你不是能更新某个底层库的。所以我觉得各有利弊吧。
|
26
kljsandjb 2019-01-13 23:04:05 +08:00 via iPhone
不说磁盘,内存这玩意不管多大都是稀缺资源😂
|
27
dalieba 2019-01-13 23:10:13 +08:00 via Android
降低开发成本,尤其是几个程序或者操作都需要一个轮子的时候。
|
28
dangyuluo 2019-01-14 01:24:37 +08:00
建议读一读《程序员的自我修养-链接、装载和库》,有真相
|
29
sdijeenx 2019-01-14 02:58:10 +08:00
磁盘空间本来是够的,自从有了 SSD 之后又不够了;
内存空间本来是够的,自从有了 DDR4 之后又不够了。😂 |
30
Ediacaran 2019-01-14 06:54:46 +08:00 via Android
插件,或者方便替换
|
31
hikkikuma1991 2019-01-14 09:08:31 +08:00
有些库没办法被静态连接,以 glibc 那一坨为代表。golang 默认也是动态链接 glibc 的。
|
32
a226679594 2019-01-14 09:27:53 +08:00
|
33
fhc023 OP @hikkikuma1991 长知识了 具体为啥必须要动态链接 大概是因为这个 https://skarnet.org/software/nsss/nsswitch.html
|
34
enenaaa 2019-01-14 09:53:13 +08:00
静态链接一个符号重名就能折腾死你。
|
35
fhc023 OP 话说这个问题原来在 YC 上就有讨论 感觉水很深呐
http://harmful.cat-v.org/software/dynamic-linking/ https://news.ycombinator.com/item?id=9629663 |
36
msg7086 2019-01-14 09:56:25 +08:00
@fhc023 #25 所以发行版更新底层库都会保证 API 不会出现 breaking change。
比如 openssl 1.0.2 和 1.0.2abcdef....opqr 都是兼容的。 而且像是 libssl libc 这种库,正是动态链接的优势所在。系统库一更新,所有依赖的软件自动受益,即使你用的软件已经好几年不更新了,只要依赖的底层库更新,一样能修正掉对应的安全漏洞。 |
37
reself 2019-01-14 10:59:58 +08:00
代码上都要做解耦,讲究代码复用呢,为啥要反其道而行?
|
38
bytelee 2019-01-14 11:32:15 +08:00
难道动态库只是为了解决磁盘和内存空间不足的问题么?
|
39
iwtbauh 2019-01-14 12:52:56 +08:00 via Android
@fhc023 #25
这就是我为什么讨厌 windows 这种大泥球的原因之一啊。你要是 windows 用户,肯定知道臭名昭著的“ DLL 地狱”问题。DLL 地狱即一个新软件可以随意升级(或降级)现有软件依赖的 DLL 库,而应用程序通常需要特定版本的库,一旦没有特定版本的库,应用程序就会崩溃。 这就是因为 windows 技术上一开始没有做好共享库版本控制问题导致的。也就是你说的这个原因。现在为了保证前向兼容采用了一种极其丑陋的方法规避问题,但没能实际解决。 而 Unix 的世界里,共享库版本控制做的非常好,一种方法是库文件名后戳通常带有版本号,应用程序依赖 libxxx.so.1 然后系统将 libxxx.so.1 符号链接到 libxxx.so.1.2.3 等版本上,系统只管升级 libxxx.so.1.x.x,库开发者保证小版本变化不会引入回归。而引入回归的大版本通常也可以和旧版本库共存。除了这种方法,还有很多种方法,比如 glibc 的符号版本控制,还有 qt 的库版本控制。。 |
40
littlewing 2019-01-14 13:19:12 +08:00
你是不是对 shared library 有什么误解? shared library 从来都是不使用从来解决内存和磁盘不够的问题的。
|
41
hilbertz 2019-01-14 13:25:09 +08:00
确实没有太大意义,共享库主要是为了商业分发
|
42
lcdtyph 2019-01-14 13:37:10 +08:00 via iPhone
@littlewing 还是解决了一些内存问题的吧?
|
43
XIVN1987 2019-01-14 14:23:04 +08:00
python 可以很方便的调用 C/C++编写的 dll 库,,如果是静态连接库的话,,必须得装 C/C++编译器才能使用,,
|
44
RqPS6rhmP3Nyn3Tm 2019-01-14 14:45:24 +08:00 via iPhone
想起了被 glibc 支配的恐惧
|
45
w01230 2019-01-14 15:12:14 +08:00
够用了也别浪费呀, 也有成本问题, ……看看 OPENWRT 的路由器~
|
46
ysc3839 2019-01-14 16:00:03 +08:00 via Android
@iwtbauh
Windows 没有共享库版本控制,那么应用需要用的库不都是自己打包吗?再怎么升级也不会影响到别的软件呀? 你可能会说 VC++ 运行库是共享的,但是 VC++ 本身不同版本是分开的,文件名中就包含有主版本号,同一个主版本要保证兼容的。 你说 Unix 共享库版本控制做的非常好,本质不是 Unix 做得好,而是大多数类 Unix 系统有包管理,通过包管理能很好地做到版本控制。像 macOS 这种没有自带包管理的系统,也是像 Windows 这样软件需要什么就自己打包的。 |
47
janxin 2019-01-14 16:03:17 +08:00
编译快算不算优点?
|
48
est 2019-01-14 16:11:33 +08:00 1
@iwtbauh dll 地狱早就被 winsxs 解决了。win98 时代说这个还有道理,现在说就是老黄历了。
linux 下不同 distro、甚至同一 distro 不同版本 之间根本谈不上 .so 兼容。那种加版本的 trick 就不要拿出来 show 了。 |
49
fhc023 OP |
50
fhc023 OP 感觉学到了很多哈 谢谢大家 如果大家有各种奇妙的关于这问题的链接都可以 po 出来
|
52
behanga 2019-01-14 16:53:35 +08:00
当你吐槽 XXX 这破 app 都 100/200 多 MB 的时候 有可能里面的 so 就没用 shared library
|
53
IdontWanToBeBan 2019-01-14 16:59:34 +08:00
随意用这不好吗。。
|
54
iwtbauh 2019-01-14 18:14:59 +08:00 via Android
|
55
fhc023 OP @est 嗯 谢谢提醒 自己写的哪些项目分别有哪些依赖都在自动化脚本里 如果有哪个出了问题 grep 下就知道哪些需要重新 link 之后重新编译有 bug 的库 然后 link 一下就完了 不需要全部重新编译 我觉得问题应该不大。
|
56
fhc023 OP @iwtbauh # 54
你说的很有道理啊,可惜我的开发环境和部署环境不是同一个 distro。比如我在 arch 上依赖 ffmpeg 某个 shared lib 写了程序 在部署环境的 debian 里跑不起来 debian 官方可能都不提供我依赖的这个 lib 版本。 |
59
kwest 2019-03-09 16:01:43 +08:00
1. 方便分发和更新,动态库更新一处即可,而不必像静态库一样把所有依赖于该库的二进制文件全部更新。
2. 节省内存和硬盘,动态库代码段被所有依赖它的程序共享并在内存中只存在一份。 |