还是不太理解 C 静态库和动态库?

285 天前
 nnegier

我看到一个描述,“为了方便,我们需要把 moon.o 、sun.o 、earth.o 这 3 个东西弄成一个东西。这种方法 就是 静态库 跟 动态库,静态库 是可以链接进去 程序自身,动态库是共享库,可以由多个程序共享节省空间,动态库只有用到的时候才会加载。”

它这里的程序是指单个应用还是指单个 C 语言文件呀?如果是单个应用,怎么说多个程序共享呢;如果是说单个 C 文件,那所谓的共享又是指啥呢;反正我横竖都弄不清,只知道都能用。(我个人背景是上层 Android 开发,使用的时候感觉没啥太大区别,当然了静态库快、动态库慢这个我能理解,像空间节省这个我没能理解)

7018 次点击
所在节点    C
42 条回复
rabbbit
284 天前
@cnbatch
许可证的原因是指 QT 这种要求必须使用动态库才可以商业使用吗?
MrKrabs
284 天前
第三方软件出漏洞了更新下动态库就好了
lolizeppelin
284 天前
假设你写了一个程序叫 nginx
你的程序依赖了以下库
ssl/gif/jpg/png/lua/gjson

如果你使用静态方式引用上述库
ssl 库更新时 你要重新编译 nginx,更新你的程序
gif 库更新时, 你要重新编译 nginx,更新你的程序
gif 库更新时, 你要重新编译 nginx,更新你的程序
....等等


如果你使用动态库方式引用上述库
ssl 库更新时,你只需要更新 ssl 库,不需要更新你的程序
ssl 库更新时,你只需要更新 gif 库,不需要更新你的程序
...等等


假设你的程序代码 1KB
ssl/gif/jpg/png/lua/gjsn 每个库都是 10MB

如果你使用动态库,你的程序编译出来就是 1KB,内存最低 1KB (简单计算)

如果你使用静态库,你的程序编译出来就是 600MB+1KB,内存最低 600MB+1KB (简单计算)
thevita
284 天前
我看 op 的主要疑惑应该是在于,用了 Android 的应用模型来理解 so 的“共享”的作用,这里的应用不一定是 android 应用

这里 op 可以看看传统 linux/windows 的 应用模型就比较好能搞明白 (因为这本身设计也主要是基于此的),以 linux 来说,应用(包含应用主程序) 和 库(包含一系列 so )是分开安装和管理的,同一个应用可能依赖相同的库,这个相同的部分就不用重复安装了

Android 正常的开发模式下(指 用 ndk 编译好 so 打包进 apk 中进行分发),因为 Android 应用沙河的存在,共享这个 so 是做不到的,这里 so 的作用就是用来实现动态加载,对接 JNI 的 api 而已.
cnbatch
284 天前
@rabbbit 差不多。但凡想要用 LGPL 的库却又不想开源自家源码,那就只能动态链接,用动态库形式。
thevita
284 天前
@thevita "同一个应用可能依赖相同的库,这个相同的部分就不用重复安装了" => "不同应用可能依赖相同的库,这个相同的部分就不用重复安装了"
meiyiliya
284 天前
我自己学了皮毛 Android APP 开发,我记得 WebView 就是 Android 自带的一个库,App 可以选择调用系统的 WebView ,也可以自己内嵌一个 Web 引擎。
前者就是动态库,N 个 APP 都可以使用同一个 WebView ,只要系统的 WebView 升级了,APP 自己是可以不动。
后者就是静态库,N 个 APP 要独立内嵌 N 个 Web 引擎,即使 Web 引擎一样也要占 N 份空间,且升级时也要独立升级。
fuckshiter
284 天前
我也有个问题,系统怎么知道这个动态库是同一个,大家都叫一样名字的话,例如 system.loadLibrary xxx.so
iorilu
284 天前
静态就是相当于直接拷贝代码合并到你代码一起编译

动态就是调用现成的模块, 不会和你代码合并一起
noahlias
284 天前
@fuckshiter 有加载顺序 我之前就是不小心设置错了 导致我的 mpv bug 了哈哈 我还为此去提 issue 找 bug 搞了好久哈哈哈
laminux29
284 天前
1.共享库就是可以给多个程序公用的公共函数集合,优点是只占一份空间,缺点是一旦被更改,依赖它的多个程序就完蛋。静态库相反。

2.共享库的出现,是因为以前磁盘、内存、带宽贵。
seeker
284 天前
静态,动态到处都会用这两个词,一般来说
静态=编译时,运行前 compile time
动态=运行时 runtime
比如一个库,静态库就是编译前把代码(编译好的)跟你的代码打包到一块,形成一个文件。动态库,就是不把代码跟你的代码打包成 1 个文件,而是在程序运行时,把库的代码载入。
其他地方的静态,动态,基本都类似意思。
qping
284 天前
@hello2090 #10 你说的就很容易懂,OP 的那段描述真的是云里雾里
nnegier
284 天前
@hello2090 #11 那 Chrome 和 Safari 怎么判断那个动态库是一样的呢?
ecnelises
284 天前
@nnegier
可以用命令打出系统/Applications 目录下的应用程序的可执行文件依赖的动态库,比如 Firefox 就是 otool -L /Applications/Firefox.app/Contents/MacOS/firefox ,你会发现大部分软件都依赖了一大堆动态库,都是同样的系统路径
WuSiYu
284 天前
主要是如今除开系统都会带的那些库,对于很多 windows 、mac 应用乃至 android app 而言,其实没有共享不共享的区别,因为他们都会随着安装包带着自己的一堆动态库,每个程序的所有文件是放在一起的,相互间很少会引用,无非是分成多个文件和集成到一个文件的区别
但对于 linux 下,用包管理器装一个软件,你会发现这个软件是打散放置在根目录下的,所有的动态库(.so )基本都会放在/lib 、/usr/lib 这种地方,在系统的标准路径里,那么其他程序也就可以用这些库,比如 debian 下 ttyd 依赖 libjson-c5 ,另一个别的软件包也会依赖 libjson-c5 ,那么此时 libjson-c.so.5 就只用存一个,这两个软件包共享这个动态库,同时运行的话在内存里也可以只加载一份,这样自然是更高效的,但必须要有一个统一的软件源(对于每个 linux 发行版而言),每个应用都得由软件源的维护者人工填好这些依赖信息,否则就没法保证你需要的这个库系统里有
hello2090
284 天前
@nnegier 不用想这么多,chrome 和 safari 的开发者知道他们用哪个库,用哪个版本。就像你需要用一个第三方的库,你肯定知道哪个版本,或者说你肯定指定了一个版本。只要这两个是同一个东西,系统就能保证。
thedinosaurmail
284 天前
静态库就是每次进程启动都要塞进内存里面, 所以每个进程都有一模一样的内容
动态库就是共享内存 share 这块内容 ,这样可以减少资源
xwwsxp
284 天前
静态库,就是将所有东西都打包到一起,带来的问题就是文件膨胀;也有好处,不太容易出现启动失败;
但是,动态库,可以参考 win 的 dll 设计了,Linux 中就是 so ,动态链接库,就是将相同功能的东西放到固定的目录,这样对于软件开发者来说,打包就没有静态库那么大;但是,一旦动态库或动态链接库出现丢失,可能很多软件就跑不了。
不过,静态库和动态库,一般都是针对 C 或 C++ 等项目;对于 Java 而言,压根不存在~
lopo
283 天前
大概意思就是:静态库是复制粘贴,动态库是超链接

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1022210

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX