静态库与动态库

文章目录

  • 库是一个二进制文件,包含的代码可被程序调用
  • 常见的有:标准C库、数学库、线程库......
  • 库是事先编译好的,可以复用的代码
  • 库的源码,可从对应的官网下载后编译,也可以直接安装二进制包
  • 在OS上运行的程序基本上都要使用库,例如linux系统的库路径:/lib /usr/lib
  • 使用库可以提高开发效率
  • Linux下包含静态库和共享库,Windows和Linux下库文件的格式不兼容

静态库

特点

  • 优势:
    • 编译(链接)时把静态库中相关代码复制到可执行文件中,运行时不再需要加载静态库,优化运行过程;
    • 程序运行时无需等待,调用接口更快,优化运行速度
  • 不足:
    • 占用更多磁盘和内存空间
    • 如静态库升级,程序也需要重新编译链接库,维护不易

创建

  • 第一步:明确库中函数的功能、返回值、参数含义
  • 第二步:编写库源码,例如hello
c 复制代码
void hello(void){
    printf("hello world\n");
}
  • 第三步:编译生成目标文件.o
    • gcc -c hello.c -o hello.o -Wall
  • 第四步:创建静态库 hello
    • ar -rsv libhello.a hello.o

静态库名字要以lib开头,后缀名为.a

没有main函数的.c 文件不能直接生成可执行文件

ar 命令参数

  • c 禁止在创建库时产生的正常消息
  • r 如果指定的文件已经存在于库中,则替换它
  • s 无论 ar 命令是否修改了库内容都强制重新生成库符号表
  • v 将建立新库的详细的逐个文件的描述写至标准输出
  • q 将指定的文件添加到库的末尾
  • t 将库的目录写至标准输出

链接静态库

  • 第一步:编写应用程序test.c
c 复制代码
#include <stdio.h>
void hello(void);
int main(int argc, const char *argv[]){
    //调用库函数
    hello();
    return 0;
}
  • 第二步:编译test.c 并链接静态库libhello.a
    • gcc -o 目标文件 源码.c -L路径 -lxxxx
      • -L 表示库所在的路径
      • -l 后面跟库的名称
      • -I 指定头文件所在路径
    • eg: gcc -o test test.c -L. -lhello

动态库

特点

  • Linux 动态库,也称为共享库,是一种在运行时由可执行文件动态链接和加载的代码库
  • 其主要特点包括:
    • 代码共享:多个程序可以共享同一个动态库,从而节省内存和磁盘空间
    • 更新无需重新编译:动态库更新后,只需要更新库文件即可,不需要重新编译使用它的程序
    • 版本控制:可以同时存在多个版本的动态库,程序可以选择使用哪个版本
    • 扩展功能:动态库可以用于扩展程序的功能,无需修改程序代码

创建

  • 第一步:明确库中函数的功能、返回值、参数含义
  • 第二步:编写库源码,例如hello.c
c 复制代码
#include <stdio.h>
void hello(void){
    printf("hello world\n");
}
  • 第三步:编译生成位置无关代码的目标文件.o
    • gcc -fPIC -c hello.c -o hello.o
  • 第四步:生成动态库(共享库)
    • $ gcc -shared hello.o -o libhello.so

链接动态库(共享库)

  • 第一步:编写应用程序test.c
c 复制代码
#include <stdio.h>
void hello(void);
int main(int argc, const char *argv[]){
    //调用库函数
    hello();
    return 0;
}
  • 第二步:链接动态库(共享库),编译可执行文件
    • gcc -o 目标文件 源码.c -L路径 -l共享库名
      • -L 表示库所在的路径
      • -l 后面跟库的名称

常见错误

  • 执行调用了动态库的可执行文件,出现错误:

./main: error while loading shared libraries: libhello.so: cannot open sharedobject file: No such file or directory

复制代码
- 含义:可执行文件所使用的动态库找不到
  • 解决办法一:
    • 找到动态库,拷贝一份到/usr/lib路径里面
    • $ sudo cp libhello.so /usr/lib/
  • 解决办法二:
    • 在 ~/.bashrc 文件里面添加语句:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:你的动态库的绝对路径
    • 使用 source ~/.bashrc 命令保存生效

静态库与动态库(共享库)的区别

  • Linux静态库与动态库(共享库)的主要区别包括文件后缀、链接方式、代码载入时间、生成的可执行文件大小、内存占用、更新与维护以及使用场景和优势等方面
  • 文件后缀与命名规则:
    • 静态库:后缀为".a",命名格式通常为"lib+库名称+.a"
    • 动态库:后缀为".so",命名格式通常为"lib+库名称+.so"
  • 链接方式与代码载入时间:
    • 静态库:在程序编译时,静态库的代码会被链接到目标代码中。因此,程序运行时将不再需要该静态库。链接过程在编译时期完成,执行时代码加载速度快
    • 动态库:在程序编译时,动态库的代码并不会被链接到目标代码中。而是在程序运行时,当需要用到动态库中的函数或类时,才将其载入内存。链接过程推迟到了运行时运行
  • 生成的可执行文件大小与内存占用:
    • 静态库:由于整个函数库的所有数据都会被整合进可执行程序中,因此生成的可执行文件通常比较大。这会导致计算机内存和磁盘的空间浪费
    • 动态库:程序在运行时执行到相关函数时才调用动态库中的相应函数,因此生成的可执行文件比较小。多个程序可以共享同一个动态库的代码,内存中只需存在一份动态库的实例,从而节省了内存空间
  • 更新与维护:
    • 静态库:如果静态库发生更改,所有使用它的程序都需要重新编译。这使得程序的更新和发布相对不便
    • 动态库:动态库的更改不会影响已经编译的程序。只需更新动态库文件,而无需重新编译程序。这使得程序的升级和维护更加简单
  • 使用场景与优势:
    • 静态库:适用于需要确保程序在所有环境中都能独立运行且不需要依赖外部库文件的场景。由于所有使用的函数都已经被编译进程序中,因此程序的运行更加稳定可靠。
    • 动态库:适用于需要节省内存和磁盘空间的场景,以及需要频繁更新库文件的场景。动态库使得多个程序可以共享同一个库文件,提高了资源的利用率。同时,动态库的升级也更加方便,只需更新库文件即可

查看库中相关信息

  • 在Linux中,nm 命令用于显示二进制文件(如可执行文件或库)的符号表
  • 通过nm命令观察库的功能与逻辑,可以应用在调试环节中
  • 当看到结果中出现T和U这样的字符时,它们代表了不同类型的符号
    • T:表示一个全局文本(代码)符号。在ELF(Executable and Linkable Format)格式的对象文件中,T通常意味着该符号是一个函数或变量,它在目标文件中定义(即它是可执行文件的一部分)
    • U:这表示一个未定义的符号。在链接阶段,如果一个符号被引用但未在链接的任何对象文件中定义,那么该符号会被标记为U。这通常意味着该符号是在其他库中定义的,或者在链接时需要通过某种方式(如链接器脚本或命令行参数)来指定其定义位置
  • nm libhello.a
latex 复制代码
hello.o:
    0000000 T hello
            U puts
  • 静态库
  • 动态库
  • 查看可执行文件使用的动态库
    • <font style="color:rgb(51,51,51);">ldd 可执行文件</font>
bash 复制代码
root@haas-virtual-machine:/mnt/hgfs/share/newIOP# ldd test
    linux-vdso.so.1 => (0x00007fff6548d000)
    libmyheby.so => /mnt/hgfs/share/newIOP/day5/libmyheby.so (0x00007f5c89521000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5c89144000)
    /lib64/ld-linux-x86-64.so.2 (0x000055fe52211000)
  • readelf 库名 读取库信息
  • objdump -d 库名 反汇编命令,实现显示可执行部分的汇编内容
相关推荐
列逍8 天前
Linux 动静态库深度解析:原理、制作与实战
linux·运维·服务器·动态库·静态库
努力的小帅13 天前
Linux_基础IO(Linux入门到精通)
linux·动态库·静态库·计算机组成原理·io操作
charlie11451419115 天前
深入理解CC++的编译与链接技术9:动态库细节
c语言·开发语言·c++·学习·动态库
边疆.18 天前
【Linux】库制作与原理
linux·运维·动态库·静态库·动态链接·静态链接
charlie11451419123 天前
深入理解CC++的编译与链接技术8:Windows和Linux是如何搜寻动态库的?
c语言·c++·动态库·编译·编译技术
RollingPin25 天前
iOS 动态库与静态库的区别
ios·framework·动态库·静态库·符号表·三方库·dyld
charlie1145141911 个月前
深入理解C/C++的编译链接技术6——A2:动态库设计基础之ABI设计接口
c语言·开发语言·c++·学习·动态库·函数
charlee441 个月前
CMake构建学习笔记30-Ceres Solver库的构建
静态库·非线性优化·cmake·buildcppdependency·ceres solver
江上清风山间明月2 个月前
LOCAL_STATIC_ANDROID_LIBRARIES的作用
android·静态库·static_android