文章目录
- 一、静态库
- 1、定义
- 2、文件扩展名
- 3、生成静态库
- 4、使用静态库
- 5、静态库的优缺点
- 二、动态库
- 1、定义
- 2、文件扩展名
- 3、生成动态库
- 4、使用动态库
- 5、动态库的优缺点
- 6、简单动态库加载
- 三、补充
一、静态库
1、定义
静态库是在编译时链接到最终的可执行文件中的库。这意味着,在程序编译时,静态库中的代码会被复制到最终的可执行文件中。
2、文件扩展名
在Linux下静态库通常以 .a 作为文件扩展名(archive file)。
3、生成静态库
(1)ar指令
功能
用于创建、修改和提取归档文件(archive files),这些归档文件通常被称为静态库(static library)。
语法
ar [参数选项] [归档文件名] [目标文件列表]
常用选项
c:创建归档文件。
r:向归档文件中添加目标文件。如果目标文件已经存在于归档文件中,则替换它。
d:从归档文件中删除目标文件。
t:列出归档文件中包含的目标文件列表。
x:从归档文件中提取目标文件。
(2)生成静态库
mystring.h
1 #pragma once 2 3 int my_strlen(const char * ptr);
mystring.c
1 #include"mystring.h" 2 3 int my_strlen(const char * ptr) 4 { 5 int count = 0; 6 while(*ptr) 7 { 8 count++; 9 ++ptr; 10 } 11 12 return count; 13 }
生成mystring.o
gcc -c mystring.c -o mystring.o
使用mystring.o 生成静态库
ar -rc libmystring.a mystring.o //命名lib***.a
4、使用静态库
假设main.c源文件使用上述的库。
1 #include"mystdio.h" 2 #include"mystring.h" 3 #include<string.h> 4 #include<stdio.h> 5 int main() 6 { 7 const char * s = "hehe"; 8 printf("%d\n",my_strlen(s)); 9 return 0; 10 }
(1)安装到系统路径下
将库拷贝到系统路径下
sudo cp libmystring.a /usr/lib
将头文件拷贝到系统路径下
udo cp mystring.h /usr/include
生成可执行文件
-l 选项:指定库名(去掉lib和后缀)
如果不指定库名,即便有路径也找不到库。
gcc main.c -o main -lmystring
运行生成的可执行文件
(2)和源文件一起
-L选项:指定库的路径。
生成可执行文件
gcc main.c -o main -L. -lmystring
运行生成的可执行文件
(3)使用带路径的库
-I选项:指定头文件的目录。
生成可执行文件
gcc main.c -o main -I./stdc/inclde -L./stdc/lib -lmystring
执行生成可执行文件
5、静态库的优缺点
优点:
- 无需额外的库文件:因为代码已经被复制到可执行文件中,所以运行时不需要额外的库文件。
- 部署简单:只需分发最终的可执行文件。
缺点:
- 增大可执行文件大小:因为每个使用静态库的程序都会包含库的副本。
- 浪费内存:如果多个程序使用同一个静态库,每个程序都会占用相同的代码空间。
- 当库文件修改时,使用当前静态库的程序可能需要重新编译。
二、动态库
1、定义
动态库(也叫共享库)是在程序运行时被链接到可执行文件中的库。这意味着,在程序运行时,动态库中的代码会被加载到内存中,并且可以被多个程序共享。
2、文件扩展名
在Linux下动态库通常以 .so(Shared Object)作为文件扩展名。
3、生成动态库
生成.o文件
gcc -c -fPIC mystring.c -o mystring.o
-fPIC 选项的作用是指示编译器生成与位置无关的代码(Position Independent Code)。这种代码可以在内存中的任何位置运行,而不需要重新定位。这对于共享库(动态库)来说是非常重要的,因为共享库在加载到进程地址空间时,其加载地址通常不是固定的,而是由操作系统动态决定的。。
生成动态库
gcc -shared -o libmystring.so mystring.o //通常以lib作为前缀
-shared 选项告诉编译器生成共享库。
4、使用动态库
(1)安装到系统路径下
将库拷贝到系统路径下
sudo cp libmystring.so /usr/lib
将头文件拷贝到系统路径下
sudo cp mystring.h /usr/include
生成可执行文件
gcc main.c -o main -lmystring
运行生成可执行文件
(2)和源文件一起或者指定路径下
生成可执行文件
如:使用指定路径:
gcc main.c -o main -I./stdc/include -L./stdc/lib -lmystring
执行生成可执行文件
执行失败了,原因如下:
找不到动态库。
为什么编译成功了,还会报这种错误呢?
因为在编译时,指定的路径是给编译器看的,所以在编译时能找到库不会出错,而在执行时,系统链接库时会在系统默认路径下找(如/usr/lib),在库中找不到所以在执行时就会报错。
如何证明?
命令 ldd [可执行文件] ,可以看到可执行文件依赖的库
怎么解决?
使用软链接,让库和系统默认路径建立软连接。
sudo ln -s /home/xzy/112/dir3/stdc/lib/libmystring.so /usr/lib/libmystring.so
再次运行可执行文件
(3)、修改环境变量
在环境变量LD_LIBRARY_PATH中加上库的路径,如果没有就创建。
添加环境变量
export LD_LIBRARY_PATH=/home/xzy/112/dir3/stdc/lib
5、动态库的优缺点
优点
- 节省磁盘和内存空间:因为多个程序可以共享同一个动态库。
- 便于更新和维护:只需更新动态库文件,而无需重新编译使用它的程序。
- 支持模块化:可以动态加载和卸载库,实现更灵活的程序设计。
缺点
- 部署复杂:需要确保动态库文件在运行时可用,可能需要额外的配置。
- 兼容性问题:不同版本的动态库可能不兼容,需要确保程序与库的版本匹配。
6、简单动态库加载
三、补充
(1)gcc/g++默认使用动态链接。
(2)如果同时提供动态库和静态库,那么默认使用动态库,如果想强制使用需要在编译指令后面加上-static选项。
(3)如果只提供静态库,不提供动态库,gcc/g++没得选,只能针对静态库才用局部的静态链接。