You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

动态/静态库分别在编译、链接、加载还是运行时完成链接?

静态库(.a/.lib)的链接时机

静态库的链接是在编译后的链接阶段完成的,具体来说:

  • 当你用gcc(或Visual Studio的编译器)编译生成目标文件(.o)后,链接器(比如ld)会处理你指定的.a静态库:它会扫描库文件,提取出你的主程序实际用到的代码和数据段,直接嵌入到最终生成的可执行二进制文件中。
  • 一旦链接完成,最终的可执行文件就和原静态库彻底独立了——哪怕后续静态库文件被修改或删除,也不会影响已生成的可执行程序的运行。
  • 这类静态库在Windows Visual Studio环境中对应的就是静态.lib文件,逻辑完全一致。
动态库(.so/.dll)的链接时机

动态库的链接分为两个关键阶段,这也是很多说法冲突的核心原因:

1. 编译时的符号解析与依赖记录

当你用gcc -o生成可执行文件时,链接器会做两件事:

  • 检查你引用的动态库(.so)中是否存在主程序调用的所有符号(函数、变量等),确保没有未定义的引用;
  • 在生成的可执行文件中写入动态库的依赖信息(比如库的名称、查找路径),但不会将动态库的代码或数据嵌入可执行文件
    这个阶段只是完成了“符号合法性验证”和“依赖声明”,并没有真正把库的代码和可执行程序关联起来。

2. 运行时的实际链接

这一步才是动态库真正和可执行程序绑定的阶段,又分两种场景:

  • 加载时链接(默认行为):当你启动可执行程序时,操作系统的动态加载器(比如Linux的ld.so、Windows的ntdll.dll)会根据可执行文件里的依赖信息,找到对应的.so/.dll文件,将其加载到内存中,然后完成符号地址的绑定——把可执行程序中对库函数的调用,映射到内存中库的实际代码地址。这个过程是在程序启动、主函数执行前完成的。
  • 显式运行时链接:你可以通过代码手动调用API(比如Linux的dlopen/dlsym、Windows的LoadLibrary/GetProcAddress),在程序运行的任意阶段主动加载动态库、获取符号地址。这种场景下,链接是完全在程序运行过程中触发的。

回到你看到的Stack Overflow回答:它提到的“运行时链接”其实是泛指上述的第二个阶段(加载时或显式运行时),而非编译链接阶段。这也是为什么动态库更新后,只要替换对应的.so文件(或通过ln命令让程序指向新的库文件),重启程序就能使用新的库代码,无需重新编译主程序。

内容的提问来源于stack exchange,提问作者FOXDeveloper

火山引擎 最新活动