Compiling

為什麼我必須在執行程序之前設置 LD_LIBRARY_PATH,即使我已經在編譯階段連結了庫位置?

  • June 10, 2021

我正在使用make. 該模型有一個Makefile通過看起來像的標誌將原始碼與依賴庫連接起來-L/lib1 -L/lib2。但是當我嘗試執行該模型時,它會失敗,除非我也確保環境變數

export LD_LIBRARY_PATH=/lib1:/lib2

並指向完全相同的庫。這對我來說似乎是多餘的。

這裡的引擎蓋下可能發生了什麼?為什麼我必須在編譯之前和執行之前有效地指定庫的位置?

這可能是一個愚蠢的問題;我對編譯機器程式碼不是很有經驗,通常只使用腳本語言。

儘管每個人都在將原始碼轉換為執行檔的通俗意義上使用編譯,但從技術上講,這是一個相當長的管道中的一個步驟:

  1. 輸入文件通過預處理器執行,生成單個翻譯單元。
  2. 預處理器的輸出被編譯成彙編。
  3. 彙編器將其作為輸入並輸出一個目標文件。
  4. 連結器將目標文件拼接在一起以生成執行檔。

$$ To be pedantic there’s no requirement the steps be separate and modern compilers typically combine them for efficiency. $$ 我們關心的是連結步驟,它將您的程式碼與標準系統庫結合起來。連結器將靜態庫中的對象直接複製到執行檔中。但是,對於共享庫,它只提供對該庫的引用。

共享庫有很多優點。您可以在不重新編譯程序的情況下更新它們,並且它們使用更少的記憶體,因為程序可以共享公共程式碼。它們還有一個明顯的缺點,即程式碼不在執行檔中。

解決方案是動態載入器,它負責在執行時解析所有共享庫引用。載入器自動執行;這樣做的指令是連結器包含在執行檔中的一件事。當然,這以載入器可以找到庫為前提。

系統庫位於標準目錄中,這很簡單。如果不是這種情況,載入程序將搜尋 LD_LIBRARY_PATH。為什麼連結器不只是將路徑放在執行檔中?因為那樣您將無法移動或更改庫。

實際上,您也無法真正移動執行檔,因為該庫位於系統搜尋路徑之外。如果它僅在庫位於 ~luke/lib 中時執行,那麼除非他可以讀取您的文件,否則您不能將其交給 joe。如果你換一份新工作,喬會很糟糕。

僅供參考,它也會以無數其他方式吸收。如果您只能在編譯時指定庫位置,除其他外,調試將成為永恆的噩夢。

引用自:https://unix.stackexchange.com/questions/425013