一個程式是怎麼變成可執行檔的?這個過程中,Linking(連結)扮演了關鍵角色。
當我們用 C/C++ 寫一個程式時,其流程如下:
.c / .cpp
原始碼編譯成 .o
(object file,目標檔)。.o
以及 Library(函式庫),合併成一個完整的執行檔(例如 a.out
或 hello.exe
)連結器「合併」的過程,就是 Linking。
舉兩個經常使用的 Library 函式庫例子,當我們在 C 語言寫:
#include <stdio.h>
#include <ctype.h>
函式庫 <stdio.h> 提供 printf()
、scanf()
等函式;<ctype.h> 提供 isalpha()
、isdigit()
、toupper()
等函式,當我們要使用這些函式時,不需要自己實作,只需要編譯器進行 Linking 就能使用。
Static Library(靜態函式庫,例如 .a
/ .lib
)
在編譯後,使用到的 Library 的函式程式碼會被寫入最終的執行檔
由於執行檔包含 Library 程式碼,因此產生的檔案比較大,且不需要連結外部的 Library 就能執行
例子:
假設撰寫 hello.c
#include <stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
若用靜態連結編譯:
gcc -static hello.c -o hello_static
這個 hello_static 檔案會比較大,因為裡面包含了 printf
的程式碼
Dynamic Library(動態函式庫,例如 .so
/ .dll
)
在執行時,程式呼叫使用到的外部的 Library
假設呼叫了 isalpha()
(來自 ),那麼程式執行的時候會去電腦裡找 libc.so
或 msvcrt.dll
(標準 C Library)
產生的執行檔比較小,但執行時必須依賴外部的 .so
或 .dll
例子:hello.c
,若用動態連結編譯:
gcc hello.c -o hello_dynamic
hello_dynamic
檔案會小很多,因為它只是在程式裡記錄「我要用 printf,執行時請去找 libc.so」。
無法在沒有 C Library 的電腦上運作,因為無法呼叫對應的 Library
類型 | 範例 | 優點 | 缺點 |
---|---|---|---|
Static Library | printf 的程式碼被打包進執行檔 |
執行時不需要依賴外部呼叫 | 執行檔體積大,更新 Library 需要重新編譯 |
Dynamic Library | 程式執行時去呼叫 libc.so 的 printf |
執行檔小 | 執行時必須要有外部 .so /.dll |
printf@GLIBC_2.2.5
在 Linux 上,我們可以用 ldd
指令:
ldd my_program
若為 Dynamic,會列出:
linux-vdso.so.1 => (0x00007ffd61d54000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3c5d2a0000)
若沒有任何輸出,代表可能是 Static。