静态库动态库区别?
静态库是编译时链接的库,需要链接进你的 Mach-O 文件里,如果需要更新就要重新编译一次,无法动态加载和更新、链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。
而动态库是运行时链接的库,使用 dyld 就可以实现动态加载、链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存。
表现形式的区别?
.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
代码编译成静态库(library),让其他开发者添加到自己的项目中。这需要你一并公布所有的公开的头文件。
链接器和解释器
链接器最主要的作用,就是将符号绑定到地址上。
解释器,是在运行时才去解析代码,这样就比在运行之前通过编译器生成一份完整的机器码再去执行的效率要低。
既然编译器效率这么高,那为什么还有人用解释器呢?所谓事有利弊,解释器可以在运行时去执行代码,说明它具有动态性,程序运行后能够随时通过增加和更新代码来改变程序的逻辑。也就是说,你写的程序跑起来后不用重新启动,就可以看到代码修改后的效果,这样就缩短了调试周期。程序发布后,你还可以随时修复问题或者增加新功能,用户也不用一定要等到发布新版本后才可以升级使用。所以说,使用解释器可以帮我们缩短整个程序的开发周期和功能更新周期。
编译时链接器做了什么?
而链接器的作用,就是完成变量、函数符号和其地址绑定这样的任务。而这里我们所说的符号,就可以理解为变量名和函数名。
如果地址和符号不做绑定的话,要让机器知道你在操作什么内存地址,你就需要在写代码时给每个指令设好内存地址。这样可读性和可维护性都会很差,比如修改代码后对地址的维护就会让你崩溃。而这种“崩溃”的罪魁祸首就是代码和内存地址绑定得太早。
链接器在链接多个目标文件的过程中,会创建一个符号表,用于记录所有已定义的和所有未定义的符号。链接时如果出现相同符号的情况,就会出现“ld: dumplicate symbols”的错误信息;如果在其他目标文件里没有找到符号,就会提示“Undefined symbols”的错误信息。
使用 dyld 加载动态库,有两种方式:
有程序启动加载时绑定和符号第一次被用到时绑定。为了减少启动时间,大部分动态库使用的都是符号第一次被用到时再绑定的方式。
尽量把动态库转成静态库节省时间
This slowdown happens because every dynamic framework adds overhead for dyld to do before an app’s
main()
function is called (known as “loading, rebasing, and binding”). Apple suggests replacing dynamic frameworks with static archives to mitigate this.
网友评论