天天看點

【C語言進階剖析】20、連結過程簡介

工程中的每個 c 語言源檔案被編譯後生成目标檔案,這些目标檔案如何生成最終的可執行程式?

連結器的作用就來了,連結器的主要作用是把各個子產品之間互相引用的部分處理好,使得各個子產品之間能夠正确的銜接。

【C語言進階剖析】20、連結過程簡介

連結分為靜态連結和動态連結,我們分别講解

由連結器在連結時将庫的内容直接加入到可執行程式中,最終的可執行檔案和中間檔案沒有關系了,可單獨運作

【C語言進階剖析】20、連結過程簡介

linux 下靜态庫的建立和使用

編譯靜态庫源碼:gcc -c lib.c -o lib.o

生成靜态庫檔案:ar -q lib.a lib.o

使用靜态庫編譯:gcc main.c lib.a -o main.out

【C語言進階剖析】20、連結過程簡介
ar 指令就是一個打包指令,将所有的靜态連結庫打包。 編譯完成後,20-1 是一個可執行檔案,該檔案不依賴一其他檔案,可單獨執行,删除所有的中間檔案對可行性檔案的執行沒有影響。

可執行程式在運作時才動态加載庫進行連結(從連結階段推遲到運作階段)

庫的内容不會進入可執行程式當中

【C語言進階剖析】20、連結過程簡介

linux 下動态庫的建立和使用

編譯動态庫源碼:gcc -shared dlib.c -o dlib.so

使用動态庫編譯:gcc main.c -ldl -o main.out

關鍵系統調用

dlopen:打開動态庫檔案

dlsym:查找動态庫中的函數并傳回調用位址

dlclose:關閉動态庫檔案

下面就看一個實際的例子:

【C語言進階剖析】20、連結過程簡介

如果我們删除庫檔案 dlib.so,再次編譯,當然運作的時候找不到動态連結庫。

【C語言進階剖析】20、連結過程簡介

靜态連結和動态連結各有優缺點:

靜态連結缺點:

浪費空間,因為每個可執行程式中對所有需要的目标檔案都要有一份副本,是以如果多個程式對同一個目标檔案都有依賴,如多個程式中都調用了printf()函數,則這多個程式中都含有printf.o,是以同一個目标檔案都在記憶體存在多個副本;

更新比較困難,因為每當庫函數的代碼修改了,這個時候就需要重新進行編譯連結形成可執行程式。

靜态連結優點:

運作速度快,因為在可執行程式中已經具備了執行程式所需要的任何東西。

動态連結優點:

多個程式在執行時共享同一份副本;

更新友善,更新時隻需要替換原來的目标檔案,無需将所有的程式再重新連結一遍。當程式下一次運作時,新版本的目标檔案會被自動加載到記憶體并且連結起來

動态連結缺點:

有一定性能損失,因為把連結推遲到了程式運作時,是以每次執行程式都需要進行連結。據估算,動态連結和靜态連結相比,性能損失大約在5%以下。這點性能損失用來換取程式在空間上的節省和程式建構和更新時的靈活性是值得的。

1、連結是指将目标檔案最終連結為可執行程式

2、根據連結方式可分為靜态連結和動态連結

靜态連結:目标檔案直接連結進入可執行程式

動态連結:在程式啟動後才動态加載目标檔案