在 C/C++ 项目开发中,理解并掌握如何编译和使用库文件是至关重要的一环。库允许你将常用的函数和代码模块化,从而提高代码重用性、简化项目管理并缩短编译时间。最常见的两种库类型是静态库 (.a)动态库 (.so)。它们各有优缺点,适用于不同的开发场景。


静态库 (.a):编译时嵌入

静态库,在 Linux 系统中通常以 .a(archive)为扩展名,在 Windows 上是 .lib,它的特点是在程序编译的链接阶段,会将库中被使用的代码直接复制到最终的可执行文件中

优点:
  • 自包含性强: 生成的可执行文件是独立的,不依赖外部库文件。这意味着你可以轻松地分发程序,而无需担心目标系统是否安装了相应的库。
  • 性能略高: 由于所有代码都在可执行文件内部,运行时无需额外的加载步骤,理论上可能会有微小的性能优势。
  • 解决依赖问题: 不存在运行时库文件丢失或版本不兼容的问题。
缺点:
  • 文件体积大: 如果多个程序都使用了同一个静态库,那么每个程序的可执行文件都会包含一份库的完整副本,导致磁盘空间占用较大。
  • 更新不便: 如果库代码需要更新,所有链接了该静态库的程序都必须重新编译。
  • 内存浪费: 运行时,每个进程都会加载库代码的独立副本到内存中。
编译流程:

编译静态库通常分为两步:

  1. 编译源文件为目标文件 (.o):
    将每个包含你希望放入库中的 C/C++ 源文件编译成目标文件,但不进行链接。这会产生 .o 文件。

    gcc -c my_source1.c -o my_source1.o
    gcc -c my_source2.c -o my_source2.o
    # ...以此类推
    
    • gcc: C/C++ 编译器。
    • -c: 指示编译器只编译源文件到目标文件,不执行链接操作。
    • -o: 指定输出的目标文件名称。
  2. 使用 ar 工具创建静态库:
    ar(archiver)是一个用于创建、修改和提取归档文件的工具。它将多个目标文件打包成一个静态库文件。

    ar rcs libmylibrary.a my_source1.o my_source2.o
    
    • ar: 归档工具。
    • rcs: ar 命令的常用选项组合:
      • r: 将指定文件插入到归档中(如果归档中已存在同名文件则替换)。
      • c: 如果归档文件不存在,则创建它。
      • s: 创建目标文件索引,这能加快链接器的查找速度。
    • libmylibrary.a: 你要创建的静态库的名称。静态库文件名通常以 lib 开头,以 .a 结尾。
链接到主程序:

创建静态库后,你可以在编译主程序时链接它:

gcc -o my_program main.c -L/path/to/your/libs -lmylibrary
  • -L/path/to/your/libs: 告诉链接器到 /path/to/your/libs 目录下查找库文件。
  • -lmylibrary: 告诉链接器链接名为 libmylibrary.a 的库。gcc 会自动在库名前加上 lib 并寻找 .a 扩展名。

动态库 (.so):运行时链接

动态库,在 Linux 系统中通常以 .so(shared object)为扩展名,在 Windows 上是 .dll(Dynamic Link Library),它的特点是在程序编译时只记录库的引用信息,而实际的库代码是在程序运行时才被加载到内存中

优点:
  • 文件体积小: 可执行文件不包含库的完整代码,因此体积更小。
  • 内存高效: 多个程序可以共享内存中同一个动态库的实例,节省系统资源。
  • 更新方便: 仅需替换动态库文件,无需重新编译链接到它的所有程序。这对于软件升级和维护非常方便。
  • 热插拔/插件机制: 许多插件系统(如浏览器插件、图像处理软件滤镜)都依赖动态库实现。
缺点:
  • 运行时依赖: 程序运行时需要动态库文件存在于指定路径。如果库文件缺失或版本不兼容,程序将无法启动或崩溃(俗称“DLL Hell”或“so hell”)。
  • 启动开销: 运行时需要额外的加载步骤,可能会有微小的启动时间开销。
编译流程:

编译动态库也分为两步:

  1. 编译源文件为位置无关代码 (PIC) 目标文件 (.o):
    动态库中的代码必须是位置无关的,这样才能在内存中的任何地址被加载和执行。

    gcc -c -fPIC my_source1.c -o my_source1.o
    gcc -c -fPIC my_source2.c -o my_source2.o
    # ...
    
    • -fPIC: 这个选项指示 GCC 生成位置无关代码。这是创建动态库所必需的。
  2. 使用 gcc 创建动态库:
    直接使用 gcc 配合 -shared 选项来创建动态库。

    gcc -shared -o libmylibrary.so my_source1.o my_source2.o
    
    • -shared: 指示 GCC 创建一个共享库(动态库)。
    • libmylibrary.so: 你要创建的动态库的名称。动态库文件名通常以 lib 开头,以 .so 结尾。
链接到主程序:

链接动态库与静态库的命令非常相似:

gcc -o my_program main.c -L/path/to/your/libs -lmylibrary
  • 与静态库的链接方式相同。但需要注意的是,这只是编译时的链接。
运行时查找动态库:

程序编译成功后,运行时系统需要知道去哪里找到这个 .so 文件。有几种常见方法:

  • 系统标准路径:libmylibrary.so 复制到系统库目录,如 /usr/lib/usr/local/lib。之后运行 ldconfig (在 Linux 上) 更新系统动态链接缓存。
  • LD_LIBRARY_PATH 环境变量: 在运行程序之前,设置 LD_LIBRARY_PATH 环境变量,使其包含库文件所在的目录。这只在当前 shell 会话中有效。
    export LD_LIBRARY_PATH=/path/to/your/libs:$LD_LIBRARY_PATH
    ./my_program
    
  • RPATH (Run-time search path): 在编译时使用 -Wl,-rpath 选项,将库路径硬编码到可执行文件中。这种方法在分发程序时非常方便,特别是当库文件与可执行文件在相对固定位置时。
    gcc -o my_program main.c -L./lib -lmylibrary -Wl,-rpath=./lib
    
    这里的 ./lib 是指程序运行时,相对其自身位置的 lib 目录。

总结

  • 小型项目或自包含应用程序: 静态库通常更简单,因为它消除了运行时的库依赖问题。
  • 大型项目、需要频繁更新的模块或插件系统: 动态库是更好的选择,因为它提供了更好的模块化、更小的可执行文件体积以及更灵活的更新机制。

理解这两种库的编译和链接机制是 C/C++ 开发者在构建健壮、高效且易于维护的应用程序时的必备技能。选择哪种库取决于你的具体项目需求和部署策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916050.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916050.shtml
英文地址,请注明出处:http://en.pswp.cn/news/916050.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汽车安全 | 汽车安全入门

引言 汽车安全不仅仅是对汽车/车辆进行物理入侵。这只是很小且简单的一部分。当你以攻击者/对手的思维去看待一辆联网汽车时,你关注的是整个车辆生态系统。这不仅包括它如何与外部实体通信,也包括它在车内如何运作。 汽车是主要的交通工具,…

CLIP与SIGLIP对比浅析

CLIP 和 SIGLIP 的核心区别在于损失函数的设计:CLIP 使用基于 softmax 的对比损失(InfoNCE),强制正样本在全局对比中压倒所有负样本,计算成本高且受限于负样本数量;SIGLIP 改用基于 sigmoid 的二元分类损失…

移动管家手机控车便捷性如何

移动管家4G手机控车-全面升级一键启动、无钥匙进入、手机启动、手机开关锁、手机开尾箱、手机寻车、车辆诊断、GPS北斗定位、电子围栏、车辆授权、车辆防盗抢、胎压检测、预约启动、车窗控制、车况提醒等功;移动管家手机控车系统(以“移动管家控车APP”为…

MySQL 8.4.4详细下载安装配置

1、下载mysql8.4.4文件,取zip文件 mysql8.4.4下载路径 MySQL 5.7.31详细下载安装配置 2、配置环境变量 1.系统—>高级系统设置—>环境变量—>系统变量 在系统变量中点击新建,变量名为量名为:MYSQL_HOME,添加你的mys…

在 Linux 上安装 `pgvector`(这是一个 PostgreSQL 的向量类型扩展,常用于处理嵌入向量,便于进行向量相似度搜索)

全文 4000 字,配图配码,已在多家企业落地验证。阅读完如有收获,文末投票告诉我你最关注的方向,我会在下一篇文章里继续深入。 0. pgvector 简介 pgvector 是一款 PostgreSQL 原生向量数据类型扩展,核心能力&#xff1…

【项目实战】——深度学习.全连接神经网络

目录 1.使用全连接网络训练和验证MNIST数据集 2.使用全连接网络训练和验证CIFAR10数据集 1.使用全连接网络训练和验证MNIST数据集 import torch from torch import nn from torchvision import datasets, transforms from torch.utils.data import DataLoader from torch im…

嵌入式学习的第三十四天-进程间通信-TCP

一、TCPTCP : 传输控制协议 传输层1. TCP特点(1).面向连接,避免部分数据丢失 (2).安全、可靠 (3).面向字节流 (4).占用资源开销大2.TCP安全可靠机制三次握手:指建立tcp连接时,需要客户端和服务端总共发送三次报文确认连接。确保双方均已做好 收发…

【爬虫】06 - 自动化爬虫selenium

自动化爬虫selenium 文章目录自动化爬虫selenium一:Selenium简介1:什么是selenium2:安装准备二:元素定位1:id 定位2:name 定位3:class 定位4:tag 定位5:xpath 定位(最常用…

2025年中国移动鸿鹄大数据实训营(大数据方向)kafka讲解及实践-第2次作业指导

书接上回,第二次作业比较容易解决,我问了ai,让他对我进行指导,按照它提供的步骤,我完成了本次实验,接下来我会标注出需要注意的细节,指导大家完成此次任务。 🎯 一、作业目标 ✔️…

三十七、【高级特性篇】定时任务:基于 APScheduler 实现测试计划的灵活调度

三十七、【高级特性篇】定时任务:基于 APScheduler 实现测试计划的灵活调度 前言 准备工作 第一部分:后端实现 - `APScheduler` 集成与任务调度 1. 安装 `django-apscheduler` 2. 配置 `django-apscheduler` 3. 数据库迁移 4. 创建调度触发函数 5. 启动 APScheduler 调度器 6…

RabbitMQ--消息顺序性

看本章之前强烈建议先去看博主的这篇博客 RabbitMQ--消费端单线程与多线程-CSDN博客 一、消息顺序性概念 消息顺序性是指消息在生产者发送的顺序和消费者接收处理的顺序保持一致。 二、RabbitMQ 顺序性保证机制 情况顺序保证情况备注单队列,单消费者消息严格按发送顺…

.net core接收对方传递的body体里的json并反序列化

1、首先我在通用程序里有一个可以接收对象型和数组型json串的反序列化方法public static async Task<Dictionary<string, string>> AllParameters(this HttpRequest request){Dictionary<string, string> parameters QueryParameters(request);request.Enab…

(10)机器学习小白入门 YOLOv:YOLOv8-cls 模型评估实操

YOLOv8-cls 模型评估实操 (1)机器学习小白入门YOLOv &#xff1a;从概念到实践 (2)机器学习小白入门 YOLOv&#xff1a;从模块优化到工程部署 (3)机器学习小白入门 YOLOv&#xff1a; 解锁图片分类新技能 (4)机器学习小白入门YOLOv &#xff1a;图片标注实操手册 (5)机器学习小…

Vue 脚手架基础特性

一、ref属性1.被用来给元素或子组件注册引用信息&#xff08;id的替代者&#xff09;2.应用在html标签上获取的是真实DOM元素&#xff0c;用在组件标签上是组件实例对象3.使用方式&#xff1a;(1).打标识&#xff1a;<h1 ref"xxx">...</h1> 或 <Schoo…

Ubuntu安装k8s集群入门实践-v1.31

准备3台虚拟机 在自己电脑上使用virtualbox 开了3台1核2G的Ubuntu虚拟机&#xff0c;你可以先安装好一台&#xff0c;安装第一台的时候配置临时调高到2核4G&#xff0c;安装速度会快很多&#xff0c;安装完通过如下命令关闭桌面&#xff0c;能够省内存占用&#xff0c;后面我们…

Word Press富文本控件的保存

新建富文本编辑器&#xff0c;并编写save方法如下&#xff1a; edit方法&#xff1a; export default function Edit({ attributes, setAttributes }) {return (<><div { ...useBlockProps() }><RichTexttagNameponChange{ (value) > setAttributes({ noteCo…

【编程趣味游戏】:基于分支循环语句的猜数字、关机程序

&#x1f31f;菜鸟主页&#xff1a;晨非辰的主页 &#x1f440;学习专栏&#xff1a;《C语言学习》 &#x1f4aa;学习阶段&#xff1a;C语言方向初学者 ⏳名言欣赏&#xff1a;"编程的核心是实践&#xff0c;而非空谈" 目录 1. 游戏1--猜数字 1.1 rand函数 1.2 sr…

UE5 UI 控件切换器

文章目录分类作用属性分类 面板 作用 可以根据索引切换要显示哪个子UI&#xff0c;可以拥有多个子物体&#xff0c;但是任何时间只能显示一个 属性 在这里指定要显示的UI的索引

scikit-learn 包

文章目录scikit-learn 包核心功能模块案例其他用法**常用功能详解****(1) 分类任务示例&#xff08;SVM&#xff09;****(2) 回归任务示例&#xff08;线性回归&#xff09;****(3) 聚类任务示例&#xff08;K-Means&#xff09;****(4) 特征工程&#xff08;PCA降维&#xff0…

Excel 将数据导入到SQLServer数据库

一般系统上线前期都会导入期初数据&#xff0c;业务人员一般要求你提供一个Excel模板&#xff0c;业务人员根据要求整理数据。SQLServer管理工具是支持批量导入数据的&#xff0c;所以我们可以使用该工具导入期初。Excel格式 第一行为字段1、连接登入的数据库并且选中你需要导入…