动态库和静态库

219 阅读5分钟

一、静态链接库与动态链接库的定义及文件格式

  1. 静态链接库

    • 定义:静态链接库是一组目标文件的归档文件,通常在编译阶段,链接器会将静态库中的代码和数据复制到最终的可执行文件中。它就像是一个工具箱,在产品制造过程中,把所需的工具直接放入产品里,使得产品完成后不依赖外部的这个工具箱。
    • 文件格式:在不同的操作系统中有不同的格式,例如在 Unix/Linux 系统中,静态库通常以.a为扩展名;在 Windows 系统中,静态库的文件格式通常为.lib
  2. 动态链接库

    • 定义:动态链接库是一种在程序运行时才被加载的库文件,编译时不会把库中的代码复制到可执行文件。当程序需要调用库中的函数时,操作系统会加载动态链接库,并将函数调用链接到库中的实际函数地址。类似于产品里只留了一个找工具的指引,在使用时才去仓库(动态链接库)找工具。

    • 文件格式:在 Linux 系统中,动态链接库通常以.so(Shared Object)为扩展名;在 Windows 系统中,动态链接库的文件格式为.dll(Dynamic Link Library)。

二、静态链接库与动态链接库的区别

  1. 链接方式

    • 静态链接库:在编译阶段,链接器将静态库中的代码和数据完整地复制到最终的可执行文件中。这意味着每个使用静态库的可执行文件都包含了一份库的代码,如同把工具从工具箱里拿出来直接放进产品里。
    • 动态链接库:编译时并不将库中的代码复制到可执行文件。而是在运行时,当程序需要调用库中的函数时,操作系统才加载动态链接库,并将函数调用链接到库中的实际函数地址,如同产品只留了一个指向工具仓库的指引,使用时才去动态库这个仓库找工具。
  2. 运行时依赖

    • 静态链接库:可执行文件因为包含了所有需要的代码,所以运行时不依赖于外部的静态链接库文件,独立性强。
    • 动态链接库:可执行文件运行时必须依赖动态链接库的存在。如果动态库丢失、版本不匹配或路径错误,程序可能无法正常运行。
  3. 内存占用和文件大小

    • 静态链接库:由于每个使用静态链接库的可执行文件都包含了一份库的代码,这会使可执行文件体积较大。不过运行时不需要额外加载库文件,内存占用相对稳定。
    • 动态链接库:可执行文件体积较小,因为没有包含库的代码。多个程序可以共享同一个动态链接库,节省磁盘空间。但运行时需要加载动态链接库到内存,且如果多个程序同时使用,可能会占用较多内存(但相对每个程序都用静态链接库还是节省的)。
  4. 更新维护

    • 静态链接库:如果静态链接库更新,使用它的可执行文件需要重新编译才能使用新的功能或修复后的代码。

    • 动态链接库:更新动态链接库不需要重新编译使用它的可执行文件,只要接口不变,程序下次运行时就可以加载更新后的动态链接库。

三、安卓和 iOS 分别使用动态库和静态库的原因

  1. 安卓使用动态链接库的原因

    • 硬件适配性:安卓设备处理器架构多样,如 ARM、x86 等。动态链接库可以针对不同架构编译,在运行时按需加载合适的版本,更好地适配硬件。
    • 内存管理:安卓设备内存资源有限,动态链接库可以被多个应用共享,节省内存空间。并且按需加载的方式避免了一次性加载大量库文件,提高资源利用效率。
    • 更新维护方便:在安卓生态系统中,动态链接库可独立于应用更新。当发现安全漏洞或性能提升需求时,只更新动态链接库即可,减少应用更新的体积和用户下载更新的成本。
    • 功能扩展灵活:支持插件化开发和功能扩展,应用可以通过加载新的动态链接库来增加新功能,如添加新的滤镜效果、新闻源解析功能等。
  2. iOS 使用静态链接库的原因

    • 安全性和保密性:静态链接库在编译时整合到应用程序中,代码难以被第三方查看和修改,有助于保护知识产权和商业秘密,对于核心算法等内容保密性强。
    • 稳定性和兼容性:依赖关系在编译时确定,不受外部库版本变化等因素影响,减少了应用崩溃的风险,保证在不同 iOS 设备和系统版本上运行的稳定性和一致性。
    • 性能优化:静态链接库的代码已在应用中,应用启动速度相对较快,且运行时不需要额外加载库文件,减少了 I/O 操作和内存开销,性能表现好。
    • 易于分发和部署:分发简单,开发者打包应用时将静态链接库和其他代码一起处理即可。用户安装应用也更简单,且应用离线状态下也能正常运行,不受网络环境限制。