靜態連結與動態連結的差異:比較函式庫的結合方式

連結是把編譯後的程式碼與它所使用的函式庫程式碼結合起來的作業。靜態連結會在建置時把所需函式庫的程式碼複製進執行檔,因此程式本身就能獨立運作。動態連結的執行檔只記錄所需的共享函式庫,在程式啟動時由作業系統載入,因此許多程式可以共用同一份副本。靜態連結便於散布,動態連結則能節省記憶體,也更容易更新。

項目靜態連結動態連結
何時進行建置時。把函式庫的程式碼複製到執行檔中載入時或執行時。由動態連結器尋找共享函式庫(.so、.dll)並進行對映
執行檔大小大小
記憶體使用量每個程式各自持有函式庫程式碼的副本共享函式庫的同一份副本可由多個行程共用
更新與安全性修補必須重新建置並重新散布程式只要更新一次函式庫就有效,不必重新建置(前提是介面相容)
啟動時間稍快稍慢。需要解析符號(多半會延遲進行)
散布自我完備。即使未安裝函式庫也能執行目標系統需要正確版本的函式庫。沒有的話會啟動失敗
執行時的成本可進行整個程式的最佳化與直接呼叫經由 GOT 或 PLT 的間接呼叫,有些微負擔
版本問題執行時不會發生程式與已安裝的函式庫可能不一致
主要用途嵌入式韌體、單一檔案的工具、最小化的容器通用作業系統上的大部分程式、外掛程式、libc 等系統函式庫

數值為具代表性的大致參考值,會因世代或產品而異。

適用於什麼情況

靜態
想要在任何地方都能執行、自我完備的二進位檔時;或是像嵌入式韌體那樣沒有作業系統載入器時。
動態
許多程式共用同一個函式庫,想節省記憶體並一次修正函式庫時。

常見問題

為什麼程式會因為找不到函式庫的錯誤而無法啟動?

因為程式是動態連結的,而所需的共享函式庫(.so 或 .dll 檔案)沒有安裝在該電腦上。請安裝函式庫,或改用靜態連結。

動態連結能節省記憶體嗎?

能。共享函式庫的同一份副本可由多個行程共用。

靜態連結比較快嗎?

稍微快一些。沒有啟動時的符號解析,也沒有經由 GOT 與 PLT 的間接呼叫,還能進行整個程式的最佳化。

為什麼動態連結有助於安全性更新?

因為共享函式庫只要修正一次,所有使用它的程式不必重新建置就能受惠。

相關名詞的解說

靜態連結(Static linking)
將所使用的函式庫程式碼複製到可執行檔中結合的方式。即使執行環境沒有函式庫也能運作,但檔案會變大,函式庫的修正必須重新建置才會反映。
動態連結(Dynamic linking)
在執行時載入共享函式庫並加以結合的方式。函式庫可在行程間共用,抽換即可反映修正,但執行環境需要相符的函式庫。
共享函式庫(Shared library)
在動態連結時於執行期載入的函式庫。在 Linux 為 .so,在 Windows 為 .dll。以位置無關程式碼建置,程式碼的分頁可由多個行程共用。
靜態函式庫(Static library)
將多個目的檔彙整為一個的封存檔(在 Linux 為 .a)。進行靜態連結時,連結器只取出需要的目的檔並組入可執行檔。

相關的比較