关于动态链接与静态链接的区别

什么是动态库与静态库

我们在生成可执行文件时,都会链接一些基础库及自己的需要的一些开发库。
这里我们可以对一个简单binary的符号表进行分析
binary符合表

图1
从图1可以看出test包含的符号表包含 dynamic_b, static_a, puts, _fini, _init等 其中puts, _fini, _init为系统基础库中的方法,所有c程序中都会包含的,dynamic_b, static_a为我们自己的开发包中的方法。

test的实现如下:

#include <stdio.h>
const char* static_a ();
const char* dynamic_b ();
int main() {
    printf("%s\n", static_a());
    printf("%s\n", dynamic_b());
    return 0;
}

这里我们的main函数,同时引用了dynamic_b和static_a 为什么符号表中,一个dynamic_b显示未定义('U’字符表示未定义)呢?
我们不妨看下test程序的生成方式

gcc -o static_a.o -c static_a.c
gcc -o static_b.o -c static_b.c 
ar rcs libstatic.a static_?.o #生成静态库

gcc -fPIC -o dynamic_a.o  -c dynamic_a.c
gcc -fPIC -o dynamic_b.o  -c dynamic_b.c
gcc -fPIC -shared -o libdynamic.so dynamic_?.o #生成动态库

gcc -g -o test main.c -L. -lstatic -ldynamic #链接动态库与静态库

在可执行程序编译生成时,会把其依赖的静态库中所有方法进行重定位和binary链接在一起,可以执行。对于其依赖的动态库中的方法会进行标记,在程序被执行时,从内存中进行查找动态库是否在内存中已被加载,若为加载,则加载之并对其依赖方法进行重定位;否则,可直接重定位。

对于静态库而言,所有依赖其的可执行程序均要加载之,在binary中拷贝一份。而对于动态库时,则是在程序执行时按需加载。
可见,动态库较静态库而言,

  1. 可以节约很多空间,多个进程依赖内存中一份即可。
  2. 升级方便,若动态库中方法实现发生变化时,无需重新编译可执行程序,只需要重启进程即可。
    缺点是,重定位过程延迟到可执行程序运行时加载,第一次符合查找过程会慢于静态链接方式。

静态库的好处是,各个程序依赖的静态库版本不会相互干扰,进程依赖的所有库都在可执行程序中。不依赖其他库。

方法同时存在于静态库和动态库

当一个方法同时存在于静态库于动态库时,按照编译参数,链接库的顺序决定最终可执行程序中使用的是哪个库中的方法。
链接顺序

图2
从图2可以看出,链接顺序会影响可执行程序的行为。

在libdynamic库中, static_a方法的实现如下

const char* static_a(){
return "fake static_a";
}

在libstatic库中, static_a方法的实现如下:

const char *static_a() {
    return __FUNCTION__;
}

可见如果同一个方法在静态库和动态库同时存在时,会以先加载为准。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值