靜態鏈結和動態鏈結

2021-08-25 11:49:18 字數 3245 閱讀 8389

動態鏈結庫、靜態庫、import庫區別

windows為應用程式提供了豐富的函式呼叫,這些函式呼叫都包含在動態鏈結庫中。其中有3個最重要的dll,kernel32.dll,它包含用於管理記憶體、程序和執行緒的各個函式;user32.dll,它包含用於執行使用者介面任務(如視窗的建立和訊息的傳送)的各個函式;gdi32.dll,它包含用於畫圖和顯示文字的各個函式。

靜態庫(static library):

函式和資料被編譯進乙個二進位制檔案(通常擴充套件名為.lib)。在使用靜態庫的情況下,在編譯鏈結可執行檔案時,鏈結器從庫中複製這些函式和資料並把它們和應用程式的其它模組組合起來建立最終的可執行檔案(.exe檔案)。

導入庫(import library):

在使用動態鏈結庫的時候,往往提供兩個檔案:乙個引入庫和乙個dll。引入庫包含被dll匯出的函式和變數的符號名,dll包含實際的函式和資料。在編譯鏈結可執行檔案時,只需要鏈結引入庫,dll中的函式**和資料並不複製到可執行檔案中,在執行的時候,再去載入dll,訪問dll中匯出的函式。在執行windows程式時,它通過乙個被稱作「動態鏈結」的程序與windows相接。乙個windows的.exe檔案擁有它使用不同動態鏈結庫的引用,所使用的函式即在那裡。當windows程式被載入到記憶體中時,程式中的呼叫被指向dll函式的入口,如果dll不在記憶體中,系統就將其載入到記憶體中。當鏈結windows程式以產生乙個可執行檔案時,你必須鏈結由程式設計環境提供的專門的「導入庫(import library)庫」。這些導入庫包含了動態鏈結庫名稱和所有windows函式呼叫的引用資訊。鏈結程式使用該資訊在.exe檔案中構造乙個表,當引導程式時,windows使用它將呼叫轉換為windows函式。

靜態庫與導入庫的區別:

導入庫和靜態庫的區別很大,他們實質是不一樣的東西。靜態庫本身就包含了實際執行**、符號表等等,而對於導入庫而言,其實際的執行**位於動態庫中,導入庫只包含了位址符號表等,確保程式找到對應函式的一些基本位址資訊。

靜態鏈結方法:#pragma comment(lib, "test.lib") ,靜態鏈結的時候,載入**就會把程式會用到的動態**或動態**的位址確定下來

靜態庫的鏈結可以使用靜態鏈結,動態鏈結庫也可以使用這種方法鏈結導入庫

動態鏈結方法:loadlibrary()/getprocessaddress()和freelibrary(),使用這種方式的程式並不在一開始就完成動態鏈結,而是直到真正呼叫動態庫**時,引導程式才計算(被呼叫的那部分)動態**的邏輯位址,然後等到某個時候,程式又需要呼叫另外某塊動態**時,引導程式又去計算這部分**的邏輯位址,所以,這種方式使程式初始化時間較短,但執行期間的效能比不上靜態鏈結的程式。

在軟體開發的過程中,大家經常會或多或少的使用別人編寫的或者系統提供的動態庫或靜態庫,但是究竟是使用靜態庫還是動態庫呢?他們的適用條件是什麼呢?

簡單的說,靜態庫和應用程式編譯在一起,在任何情況下都能執行,而動態庫是動態鏈結,顧名思義就是在應用程式啟動的時候才會鏈結,所以,當使用者的系統上沒有該動態庫時,應用程式就會執行失敗。再看它們的特點:

動態庫:

1.共享:多個應用程式可以使用同乙個動態庫,啟動多個應用程式的時候,只需要將動態庫載入到記憶體一次即可;

2.開發模組好:要求設計者對功能劃分的比較好。 

靜態庫:**的裝載速度快,執行速度也較快,因為編譯時它只會把你需要的那部分鏈結進去,應用程式相對比較大。但是如果多個應用程式使用的話,會被裝載多次,浪費記憶體。

綜上,我個人認為,如果你的系統上有多個應用程式都使用該庫的話,就把它編譯成動態庫,這樣雖然剛啟動的時候載入比較慢,但是多工的時候會比較節省記憶體;如果你的系統上只有一到兩個應用使用該庫,並且使用的api比較少的話,就編譯成靜態庫吧,一般的靜態庫還可以進行裁剪編譯,這樣應用程式可能會比較大,但是啟動的速度會大大提高。

1. ld會去找gcc命令中的引數-l

2. 再找gcc的環境變數library_path

3. 再找內定目錄 /lib /usr/lib /usr/local/lib 這是當初compile gcc時寫在程式內的

動態鏈結時、執行時搜尋路徑順序:

1. 編譯目標**時指定的動態庫搜尋路徑

2. 環境變數ld_library_path指定的動態庫搜尋路徑

3. 配置檔案/etc/ld.so.conf中指定的動態庫搜尋路徑

4. 預設的動態庫搜尋路徑/lib

5. 預設的動態庫搜尋路徑/usr/lib

有關環境變數:在linux下編譯鏈結或執行c/c++程式時可能會遇到找不到標頭檔案,找不到庫檔案的錯誤,簡單總結一下這些錯誤的解決方法

1,找不到標頭檔案

解決方法一:在編譯時使用 -i 來指定標頭檔案的路徑,例如把頭檔案放在 /home/user/include/ 目錄下,則在編譯時加上 -i /home/user/include/ ,如有多個目錄,可多次使用-i來指定

解決方法二:將標頭檔案的路徑加入環境變數cpath中,如 export cpath=" /home/user/include/",也可以根據情況使用下面的三個環境變數:

c_include_path 編譯c程式時使用的環境變數,用於查詢標頭檔案。

cplus_include_path 編譯c++程式時使用的環境變數,用於查詢標頭檔案。

objc_include_path 編譯obj-c程式時使用的環境變數,用於查詢標頭檔案。

cpath 編譯c/c++/obj-c程式時使用的環境變數,用於查詢標頭檔案。

2,鏈結時找不到庫檔案

解決方法一:在鏈結時使用-l引數來指定庫的路徑,例如把某個自己製作的動態庫放在/home/user/lib/目錄下了,則鏈結程式時加上-l/home/user/lib/,同時可以使用-l來指定庫的名稱,如指定執行緒庫:-lpthread

解決方法二:把庫檔案放入系統的庫檔案目錄下,如/lib,/usr/lib等,作業系統執行該程式時會自動到這些目錄下找庫檔案

解決方法三:把庫檔案所在的目錄加入library_path環境變數中,如 export library_path=" /home/user/lib/"

3,執行時找不到動態庫

解決方法一:把庫檔案放入系統的庫檔案目錄下,如/lib,/usr/lib等

解決方法二:把庫檔案所在的目錄加入ld_library_path環境變數中,如 export ld_library_path=" /home/user/lib/"

靜態鏈結和動態鏈結

靜態載入dll dll工程b 專案屬性 配置屬性 常規 配置型別 動態庫 dll 在宣告檔案中,宣告匯出函式 declspec dllexport int xx 如果是c檔案,要在c 檔案中被呼叫,註明extern c 可以 ifdef cplusplus extern c endif 呼叫dll的...

靜態鏈結和動態鏈結

1 靜態鏈結庫只包含 lib檔案 動態鏈結庫包含 lib檔案和dll檔案,靜態鏈結庫中不能再包含其他的動態鏈結庫或者靜態庫,而在動態鏈結庫中還可以再包含其他的動態或靜態鏈結庫。此外他們都會用到定義了函式和相關資料結構的.h標頭檔案,其中 h標頭檔案是編譯時必須的,lib是鏈結時需要的,dll是執行時...

靜態鏈結和動態鏈結

靜態鏈結 由於在我們實際的開發中,不可能將他們都放在乙個檔案中執行,所以將他們生成.o檔案進行,從而要將他們進行鏈結,從而實現乙個可以執行的程式,這個過程就是靜態鏈結 靜態庫 是由多個多個.o檔案壓縮打包形成的乙個檔案 靜態鏈結的優點 他在執行的時候都已經將副本都放入了檔案中,所以執行的速度變快 缺...