這次分享的宗旨是——讓大家學會建立與使用靜態庫、動態庫,知道靜態庫與動態庫的區別,知道使用的時候如何選擇。這裡不深入介紹靜態庫、動態庫的底層格式,記憶體布局等,有興趣的同學,推薦一本書《程式設計師的自我修養——鏈結、裝載與庫》。
庫是寫好的現有的,成熟的,可以復用的**。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的**都從零開始,因此庫的存在意義非同尋常。
本質上來說庫是一種可執行**的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。
所謂靜態、動態是指鏈結。回顧一下,將乙個程式編譯成可執行程式的步驟:
之所以成為【靜態庫】,是因為在鏈結階段,會將彙編生成的目標檔案.o與引用到的庫一起鏈結打包到可執行檔案中。因此對應的鏈結方式稱為靜態鏈結。
試想一下,靜態庫與彙編生成的目標檔案一起鏈結為可執行檔案,那麼靜態庫必定跟.o檔案格式相似。其實乙個靜態庫可以簡單看成是一組目標檔案(.o/.obj檔案)的集合,即很多目標檔案經過壓縮打包後形成的乙個檔案。
靜態庫特點總結:
l 靜態庫對函式庫的鏈結是放在編譯時期完成的。
l 程式在執行時與函式庫再無瓜葛,移植方便。
linux下使用ar工具、windows下vs使用lib.exe,將目標檔案壓縮到一起,並且對其進行編號和索引,以便於查詢和檢索。一般建立靜態庫的步驟如圖所示:
通過上面的介紹發現靜態庫,容易使用和理解,也達到了**復用的目的,那為什麼還需要動態庫呢?
為什麼還需要動態庫?
為什麼需要動態庫,其實也是靜態庫的特點導致。
空間浪費是靜態庫的乙個問題。
動態庫在程式編譯時並不會被連線到目標**中,而是在程式執行是才被載入。不同的應用程式如果呼叫相同的庫,那麼在記憶體裡只需要有乙份該共享庫的例項,規避了空間浪費問題。動態庫在程式執行是才被載入,也解決了靜態庫對程式的更新、部署和發布頁會帶來麻煩。使用者只需要更新動態庫即可,增量更新。
動態庫特點總結:
l 動態庫把對一些庫函式的鏈結載入推遲到程式執行的時期。
l 可以實現程序之間的資源共享。(因此動態庫也稱為共享庫)
l 將一些程式公升級變得簡單。
l 甚至可以真正做到鏈結載入完全由程式設計師在程式**中控制(顯示呼叫)。
window與linux執行檔案格式不同,在建立動態庫的時候有一些差異。
l 在windows系統下的執行檔案格式是pe格式,動態庫需要乙個dllmain函式做出初始化的入口,通常在匯出函式的宣告時需要有_declspec(dllexport)關鍵字。
l linux下gcc編譯的執行檔案預設是elf格式,不需要初始化入口,亦不需要函式做特別的宣告,編寫比較方便。
與建立靜態庫不同的是,不需要打包工具(ar、lib.exe),直接使用編譯器即可建立動態庫。
編譯靜態庫編譯動態庫
編譯靜態庫 cr標誌告訴ar將object檔案封裝 archive 我們可以使用nm s 命令來檢視.a檔案的內容 ar cr libmyhello.a hello.o 或 cvr 編譯動態庫 gcc c fpic test1.c gcc c fpic test2.c fpic告訴gcc將源 編譯成...
關於靜態庫與動態庫 Linux C
靜態庫 首先將原始檔編譯成目標檔案 gcc c a.c b.c 生成靜態庫 ar rc libstatic.a a.o b.o 共享庫 同靜態庫一樣編譯成目標檔案 gcc c a.c b.c 生成共享庫 gcc fpic shared o libshared.so a.o b.o 靜態庫和動態庫都是...
gcc編譯靜態庫 動態庫
今天,乙個同事編譯靜態庫,我也趁此機會在溫習一下,先google一下,然後在自己實驗。首先,在網上抄個例子,內容如下 建靜態庫 hellos.h ifndef hello s h define hello s h void prints char str endif hellos.c include...