news 2026/6/10 16:28:04

静态库与动态库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
静态库与动态库

文章目录

  • 静态库
    • 特点
    • 创建
      • ar 命令参数
    • 链接静态库
  • 动态库
    • 特点
    • 创建
    • 链接动态库(共享库)
      • 常见错误
  • 静态库与动态库(共享库)的区别
  • 查看库中相关信息

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

静态库

特点

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

创建

  • 第一步:明确库中函数的功能、返回值、参数含义
  • 第二步:编写库源码,例如hello
voidhello(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
#include<stdio.h>voidhello(void);intmain(intargc,constchar*argv[]){//调用库函数hello();return0;}
  • 第二步:编译test.c 并链接静态库libhello.a
    • gcc -o 目标文件 源码.c -L路径 -lxxxx
      • -L 表示库所在的路径
      • -l 后面跟库的名称
      • -I 指定头文件所在路径
    • eg:gcc -o test test.c -L. -lhello

动态库

特点

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

创建

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

链接动态库(共享库)

  • 第一步:编写应用程序test.c
#include<stdio.h>voidhello(void);intmain(intargc,constchar*argv[]){//调用库函数hello();return0;}
  • 第二步:链接动态库(共享库),编译可执行文件
    • 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
hello.o: 0000000 T hello U puts
  • 静态库

  • 动态库

  • 查看可执行文件使用的动态库
    • <font style="color:rgb(51,51,51);">ldd 可执行文件</font>
root@haas-virtual-machine:/mnt/hgfs/share/newIOP# ldd testlinux-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 库名反汇编命令,实现显示可执行部分的汇编内容
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 11:01:48

Arduino驱动LED入门:项目应用完整指南

从点亮第一颗LED开始&#xff1a;Arduino实战入门全解析你有没有过这样的经历&#xff1f;手握一块Arduino板&#xff0c;几根跳线&#xff0c;一个LED&#xff0c;却怎么也点不亮它。电压测了、代码传了、引脚对了&#xff0c;可灯就是不亮——别担心&#xff0c;这几乎是每个…

作者头像 李华
网站建设 2026/6/9 20:14:07

GPU算力资源如何变现?通过技术博客引流销售Token

GPU算力资源如何变现&#xff1f;通过技术博客引流销售Token 在AI模型训练动辄需要数十小时、甚至上百张GPU卡的今天&#xff0c;拥有高性能计算资源的人&#xff0c;是否只能让这些“数字印钞机”闲置吃灰&#xff1f;而另一边&#xff0c;无数开发者却因环境配置复杂、驱动版…

作者头像 李华
网站建设 2026/6/10 12:30:06

SSH远程访问PyTorch-CUDA-v2.6镜像,实现高效模型训练

SSH远程访问PyTorch-CUDA-v2.6镜像&#xff0c;实现高效模型训练 在AI研发日益工程化的今天&#xff0c;一个常见的困境是&#xff1a;研究人员手握前沿算法&#xff0c;却卡在“环境配不起来”或“本地显卡太弱”的瓶颈上。尤其当团队协作开发时&#xff0c;“在我机器上能跑”…

作者头像 李华
网站建设 2026/6/10 12:46:42

GitHub项目复现困难?用PyTorch-CUDA镜像统一实验环境

GitHub项目复现困难&#xff1f;用PyTorch-CUDA镜像统一实验环境 在深度学习领域&#xff0c;你是否经历过这样的场景&#xff1a;从GitHub克隆了一个热门项目&#xff0c;满怀期待地运行python train.py&#xff0c;结果却卡在了第一行——“ImportError: libcudart.so.11.0: …

作者头像 李华
网站建设 2026/6/10 6:33:15

Linux线程错误调试指南:从原理到实践

Linux线程错误调试指南&#xff1a;从原理到实践1. 线程调试概述2. 基础调试工具2.1 GDB调试器2.2 Valgrind工具集2.3 strace和ltrace3. 高级调试技术3.1 死锁检测3.2 竞态条件检测4. 实战案例分析4.1 案例一&#xff1a;资源泄漏4.2 案例二&#xff1a;条件变量误用5. 性能分析…

作者头像 李华