靜態庫和動態庫

2021-10-09 04:08:12 字數 3124 閱讀 6376

庫是寫好的,現有的,成熟的,可以復用的**。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的**都從零開始,因此庫的存在意義非同尋常。本質上來說,庫是一種可執行**的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。所謂靜態、動態是指鏈結。將乙個程式編譯成可執行程式的步驟:

之所以稱為【靜態庫】,是因為在鏈結階段,會將彙編生成的目標檔案.o與引用到的庫一起鏈結打包到可執行檔案中。因此對應的鏈結方式稱為靜態鏈結。

試想一下,靜態庫與彙編生成的目標檔案一起鏈結為可執行檔案,那麼靜態庫必定跟.o檔案格式相似。其實乙個靜態庫可以簡單看成是一組目標檔案(.o/.obj檔案)的集合,即很多目標檔案經過壓縮打包後形成的乙個檔案。靜態庫特點總結如下:

靜態庫對函式庫的鏈結是放在編譯時期完成的。

程式在執行時與函式庫再無瓜葛,移植方便。

下面編寫一些簡單的四則運算c++類,將其編譯成靜態庫給他人用,標頭檔案如下所示:

#pragma once

class

staticmath

;

linux下使用ar工具、windows下vs使用lib.exe,將目標檔案壓縮到一起,並且對其進行編號和索引,以便於查詢和檢索。一般建立靜態庫的步驟如圖所示:

linux下建立與使用靜態庫

1)linux靜態庫命名規則:

linux靜態庫命名規範,必須是"lib[your_library_name].a":lib為字首,中間是靜態庫名,擴充套件名為.a。

2)建立靜態庫(.a):

1.首先,將**檔案編譯成目標檔案.o(staticmath.o)

//注意帶引數-c,否則直接編譯為可執行檔案

g++-c staticmath.cpp

2.通過ar工具將目標檔案打包成.a靜態庫檔案

//生成靜態庫libstaticmath.a

ar -crv libstaticmath.a staticmath.o

3)使用靜態庫

#include

"staticmath.h"

#include

using

namespace std;

intmain

(int argc,

char

* ar**)

4)編譯的時候,指定靜態庫的搜尋路徑(-l選項)、指定靜態庫名(不需要lib字首和.a字尾,-l選項)。

g++ teststaticlibrary.cpp -l.

./staticlibrary -lstaticmath

靜態庫的缺點:

1)靜態庫間浪費空

2)靜態庫對程式的更新、部署和發布頁會帶來麻煩。如果靜態庫libxx.lib更新了,所有使用它的應用程式都需要重新編譯、發布給使用者。

動態庫在程式編譯時並不會被連線到目標**中,而是在程式執行是才被載入。不同的應用程式如果呼叫相同的庫,那麼在記憶體裡只需要有乙份該共享庫的例項,規避了空間浪費問題。動態庫在程式執行時才被載入,也解決了靜態庫對程式的更新、部署和發布頁會帶來麻煩。使用者只需要更新動態庫即可,增量更新。

動態庫特點總結:

動態庫把對一些庫函式的鏈結載入推遲到程式執行的時期。 

可以實現程序之間的資源共享。(因此動態庫也稱為共享庫)

將一些程式公升級變得簡單。

甚至可以真正做到鏈結載入完全由程式設計師在程式**中控制(顯示呼叫)。

linux下建立與使用動態庫與建立靜態庫不同的是,不需要打包工具(ar、lib.exe),直接使用編譯器即可建立動態庫。

針對於實際庫檔案,每個共享庫都有個特殊的名字「so name」。在程式啟動後,程式通過這個名字來告訴動態載入器,該載入哪個共享庫。在檔案系統中,soname僅是乙個鏈結到實際動態庫的鏈結。對於動態庫而言,每個庫實際上都有另乙個名字給編譯器來用。它是乙個指向實際庫映象檔案的鏈結檔案(lib+soname+.so)

2)建立動態庫(.so):

編寫四則運算動態庫**(如上靜態庫**)

1.首先,生成目標檔案,此時要加編譯器選項-fpic

//-fpic 建立與位址無關的編譯程式(position independent code)

//是為了能夠在多個應用程式間共享。

g++-fpic -c dynamicmath.cpp

2.然後,生成動態庫,此時要加鏈結器選項-shared

//-shared指定生成動態鏈結庫

g++-shared -o libdynmath.so dynamicmath.o

3)編寫使用動態庫的**(如上靜態庫**)

4)引用動態庫編譯成可執行檔案(跟靜態庫方式一樣)

g++ testdynamiclibrary.cpp -l.

./dynamiclibrary -ldynmath

注意:

1.當系統載入可執行**時候,能夠知道其所依賴的庫的名字,但是還需要知道絕對路徑。此時就需要系統動態載入器(dynamic linker/loader)。

2.對於elf格式的可執行程式,是由ld-linux.so*來完成的,它先後搜尋elf檔案的 dt_rpath段—環境變數ld_library_path—/etc/ld.so.cache檔案列表—/lib/或/usr/lib 目錄找到庫檔案後將其載入記憶體。

庫(靜態庫和動態庫)

一 靜態庫 以c語言的形式生成庫 h中extern c int add int int extern c int sub int int 二.測試靜態庫 將.h和.lib放入 h ifdef cplusplus c 程式設計師用c的方式開啟 extern c int add int int exte...

靜態庫和動態庫

一。靜態庫 靜態庫的優點在於使用簡單,編譯快速。靜態庫在應用程式生成時,已經編譯成為可重定位的目標檔案,因此可以不必再編譯,節省編譯時間,以最短的時間生成可執行程式。步奏 a。建立靜態庫 1 在編輯器中編輯其靜態庫函式 static lib.c 2 在shell中編譯該原始檔,生成乙個可重定位的目標...

靜態庫和動態庫

靜態庫 lib 中相當於存放了所有的源 包括他引入的其他靜態lib檔案.其實是所有cpp編譯後對應的.obj檔案的打包 所以靜態lib都比較大。動態庫dll也有lib但是這個lib,只是用來幫助程式在鏈結時定位dll中的函式的位址的。所以會在exe載入時才重定位函式的位址。重定位就是根據鏈結的這個l...