静态库/动态库
[TOC]
形式
一般来说,Windows的静态库文件扩展名是 .lib,动态库文件扩展名是 .dll (Dynamic-Link Libraries);Linux的静态库扩展名是 .a,动态库扩展名是 .so (Shared Object)
Linux系统存储的库的位置一般在:/lib 和 /usr/lib。 在 64 位的系统上有些库也可能被存储在/usr/lib64 下。库的头文件一般会被存储在 /usr/include 下或其子目录下。
Linux库有两种,一种是静态库,其命令规则为 libxxx.a;一种是共享库,其命令规则为 libxxx.so
生成
静态库生成
step1 编译生成.o文件
1 | gcc -c hello.c |
此时将会生成一个hello.o文件
-c 和含义:只编译,不链接
step2 使用.o文件生成 .a静态库
1 | ar -crv libhello.a hello.o |
-crv是ar命令的选项:c,r,v分别代表crate,replace,verbose
-c
(create):- 表示创建一个新的静态库文件(即
libhello.a
)。 - 如果库文件已经存在,
-c
不会报错,而是继续执行操作。 - 如果没有此选项,
ar
在库文件不存在时可能会提示错误。
- 表示创建一个新的静态库文件(即
-r
(replace):- 将一个或多个目标文件(如
hello.o
)添加到静态库中。 - 如果静态库中已经存在同名文件,则替换它。
- 如果静态库中不存在该文件,则会新增该文件。
- 将一个或多个目标文件(如
-v
(verbose):- 显示详细信息。
- 在执行操作时,会列出具体处理了哪些目标文件。
动态库生成
1 | gcc -shared -fPIC -o libhyhello.so hello.o |
1 | gcc -o hello main.c libhyhello.so |
-shared
- 指定生成一个共享库(动态库,
.so
文件) - 共享库是运行时动态加载的,适用于多进程共享代码,减少内存占用
-fPIC
- 生成位置无关代码(Position-Independent Code)
- 作用: 共享库在内存中加载到任何地址都能正常运行,这对于动态库至关重要
hello.o
必须是通过-fPIC
编译生成的,确保目标代码是位置无关的
-o libhyhello.so
- 指定输出文件名为
libhyhello.so
,这是动态库的标准命名格式 - Linux 系统中,动态库通常以
lib
开头,扩展名为.so
(shared object)
hello.o
- 输入文件,是先前用
gcc
编译生成的目标文件
使用
方法一
1 | gcc -o hello main.c -L. -lhello |
-L.
- 指定库的搜索路径为当前目录 (
.
)。 - 链接器在查找静态库或动态库时,除了默认的路径(如
/usr/lib
、/usr/local/lib
),也会在当前目录中查找。 - 作用: 如果静态库文件
libhello.a
或动态库文件libhello.so
位于当前目录,这个选项确保它们能够被正确找到。
-lhello
- 表示链接名为
hello
的库。 - 工作原理:
- 链接器会自动寻找以下文件:
- 静态库:
libhello.a
- 动态库:
libhello.so
- 静态库:
- 搜索路径包括默认路径和通过
-L
指定的路径(这里是当前目录.
)。
- 链接器会自动寻找以下文件:
方法二
1 | gcc main.c libhyhello.a -o hello |
方法三
1 | gcc -c main.c |
GCC命令相同时,会先执行.a文件,还是会先执行.so文件?
先删除除.c和.h文件外的所有文件,然后再编译形成.o文件,生成.o文件后,再由.o文件分别生成.a文件和.so文件。
执行程序后,发现当静态库和动态库同名时,gcc 命令将优先使用动态库,默认去连/usr/lib 和/lib 等目录中的动态库。
静态库与动态库的区别
每一个程序在使用静态库时,都会将静态库文件拷贝一份添加到自身。如果有多个程序都要使用该静态库文件时,都会给自身添加一份拷贝,这就导致会产生空间浪费。在源文件较少时不明显,但如果在一个项目中,静态库文件本身就比较大,并且使用该静态库文件的源程序很多,这就会造成大量内存浪费。
而动态库文件在被使用时,会对所有想使用该动态库的源程序添加一个标记,在程序执行时再链接动态库文件使用。这就是动态库的优点,也是动态库被称为共享库的原因。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 WHAT AM I ?!
评论