You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

程序如何在动态库中查找符号?动态库更新后主程序无需重编的疑问

动态库符号查找的运行时机制问题

代码示例

main.c

#include <stdio.h>
#include "mylib.h"

int main(int argc, char **argv) {
    printf("%d\n", foo());
}

mylib.h

#pragma once

int foo();

mylib.c

#include "mylib.h"

int foo() { return 5; }

编译与现象

将mylib编译为动态库并链接到main后,通过ldd命令可查看main对动态库的依赖:

>>> ldd main                                                                                                                
...
libmylib.so => /some_path/libmylib.so
...

修改mylib.c并重新编译动态库后,foo符号的地址会发生变化,但无需重新编译或链接main程序即可正常运行。

问题

符号查找是否在运行时进行,就像使用dlopen加载库那样,且main程序中不存储外部符号地址?

回答

不是完全和dlopen一致的运行时查找逻辑,但核心确实是**main程序不会存储外部符号的固定地址**,而是由动态链接器在程序启动阶段完成符号地址的绑定工作。

具体细节如下:

  • 编译链接main时,编译器只会为foo预留一个符号引用占位,不会写入实际内存地址。链接器会将该符号标记为需要动态解析的外部符号,同时记录main依赖的动态库信息。
  • 当运行main时,操作系统的动态链接器(比如Linux下的ld-linux.so)会先加载依赖的libmylib.so,然后遍历main中所有未解析的符号,在已加载的动态库中找到foo的实际地址,完成地址重定位——把main中调用foo的指令位置替换成动态库中foo的当前地址。
  • 这个绑定过程默认在程序启动时一次性完成(可通过LD_BIND_NOW环境变量强制生效),而非每次调用foo时才执行查找。而dlopen属于显式动态加载,是在程序运行的任意阶段手动触发库加载和符号查找,和这种隐式的动态链接机制存在区别。

因此修改动态库后,只要新库中仍存在foo符号,动态链接器在下次启动main时会重新解析绑定新的地址,自然不需要重新编译main。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 22:20:46