靜態鏈結庫和動態鏈結庫

2021-07-29 13:12:33 字數 2527 閱讀 3153

什麼是庫?
庫是寫好的現有的,成熟的,可以復用的**。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的**都從零開始,因此庫的存在意義非同尋常

本質上來說庫是一種可執行**的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。 windows上對應的是.lib .dll linux上對應的是.a .so

在這裡先介紹下linux下的gcc編譯的幾個選項

g++ -c hellospeak.cpp
會將hellospeak.cpp 選項 -c 用來告訴編譯器編譯源**但不要執行鏈結,輸出結果為物件檔案。檔案預設名與原始碼檔名相同,只是將其字尾變為 .o。例如,上面的命令將編譯原始碼檔案hellospeak.cpp 並生成物件檔案 hellospeak.o;

$ g++ hellospeak.cpp speak.cpp -o hellospeak
如果沒有-o和後面的引數,編譯器採用預設的 a.out

本例中就會生成hellospeak 這樣的可執行程式

圖:編譯過程

靜態庫

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

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

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

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

linux下建立與使用靜態庫

linux靜態庫命名規則

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

建立靜態庫(.a)

通過上面的流程可以知道,linux建立靜態庫過程如下:

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

g++ -c staticmath.cpp

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

l 然後,通過ar工具將目標檔案打包成.a靜態庫檔案

ar -crv libstaticmath.a staticmath.o

生成靜態庫libstaticmath.a

-------------------------------分割線------------------------

動態庫

通過上面的介紹發現靜態庫,容易使用和理解,也達到了**復用的目的,那為什麼還需要動態庫呢?

為什麼還需要動態庫?

為什麼需要動態庫,其實也是靜態庫的特點導致。

l 空間浪費是靜態庫的乙個問題。

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

動態庫特點總結:

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

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

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

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

window與linux執行檔案格式不同,在建立動態庫的時候有一些差異。

l 在windows系統下的執行檔案格式是pe格式,動態庫需要乙個dllmain函式做出初始化的入口,通常在匯出函式的宣告時需要有_declspec(dllexport)關鍵字

l linux下gcc編譯的執行檔案預設是elf格式,不需要初始化入口,亦不需要函式做特別的宣告,編寫比較方便。

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

靜態鏈結庫和動態鏈結庫

其實再vc中,我們所用得所有api函式都封裝再下列三個dll檔案中 kernel32.dll 用於管理記憶體,程序和執行緒得各個函式 user32.dll 用於執行使用者介面任務,如視窗的建立和訊息的傳遞的各個函式 gdi32.dll 用於顯示文字和畫圖的各個函式 動態鏈結庫 我們再使用動態庫的時候...

靜態鏈結庫和動態鏈結庫

靜態鏈結庫 win32 static library 呼叫libtest.lib 動態dll win32 dynamic link library 跟librest的生成是一樣的 動態呼叫 成的.lib 和.dll 檔案拷入dllcall 工程所在的路徑,dllcall 執行下列 dll 中匯出函式...

靜態鏈結庫和動態鏈結庫

以前的時候寫過這方面的部落格,當時寫的時候都覺得已經懂了。今天閒著沒事幹,和咚哥他們去大華校招筆試遇到了這個問題。我突然間發現sdk沒寫三個月,把dll都忘記了。回來看了下,複習下。以前寫過程式的裝載和鏈結的部落格,那是os上面比較理論的。實際用函式庫的時候主要分為,靜態庫和動態庫,這裡就簡簡單單地...