C/C++ 編程:掌握靜態庫與動態庫的編譯

在 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、連接登入的數據庫并且選中你需要導入…