Linux下,聯結器ld鏈結順序的總結

2021-09-08 10:29:25 字數 1269 閱讀 7345

原來ld對於鏈結一系列的庫的順序是很敏感的,不然會報undefined referenced 的函式符號錯誤,意思就是未找到函式定義。實際上庫是能正確開啟的。如果庫liba.a依賴於庫libb.a,那麼聯結器的引數應該ln -la -lb,   必須這樣寫。不然就會錯誤。

這個看來是歷史的遺留問題。說白了就是,如果你確定某個庫不重要,就放到最後,也就是說,庫的載入順序是按順序進行的,從左到右,優先順序最高,這也是遠古時代機器太破的原因,內在和硬碟包括cpu都是極其稀罕珍貴的。所以要你提前搞定哪些需要哪些不需要,一旦需要,就載入上去,不需要就不要載入上去。這樣就可以解釋上面的錯誤了,編譯器載入到socketcomm後,發現還有依賴庫,再往後找,木有咧,於是就錯了。

也就是說,被依賴的盡量放到後面,讓大家可以共用。

這就引申同來了另外乙個問題,如果有多個庫,使用了相同的函式名或者類名,結構體名稱會怎麼樣?

可以使用nm和readelf、ldd等命令來檢視你的庫的依賴和符號表以及匯出的函式符號等。這樣就可以來驗證上面的因為順序造成的不同的編譯結果。

把測試的庫分成動、動;靜、靜;動靜三種情況。

第一種情況:靜靜庫都包含有相同的名字函式

gcc -l./ main.c -la -lb

編譯報錯,在multiple definition of `***'。重複定義函式。

第二種情況:動動庫

這個得看載入的順序,上面說過,從左開始,按需載入。

gcc main.c ./libb.so ./liba.so

gcc main.c ./liba.so ./libb.so

這樣的鏈結方式為隱式鏈結,或者說載入時鏈結,而前面的靜態庫為編譯時連線。

也就是說,編譯的順序確定到底呼叫哪個庫中的同名函式。

第三種情況:動動,但是是動態載入,而不上面的靜態載入。

gcc main.c -ldl ./liba.so ./libb.so

gcc main.c -ldl ./libb.so ./liba.so

沒有加鏈結選項時,跟第二種情況一樣。加了l選項後,指定哪上載入哪個。

libb為靜態鏈結!, liba為動態載入.

gcc -l./ main.c -ldl –lb

動態庫的庫名顯示的加載入編譯選項中

gcc -l./ main.c -ldl -lb ./liba.so

gcc -l./ main.c -ldl ./liba.so -lb

在有靜態和動態時,不把動態庫庫名顯示加入編譯選項,輸出是正常的,如果加進去以靜態庫為主和link順序無關。

references:

linux下的軟連線和硬鏈結

linux鏈結概念 linux鏈結分兩種,一種被稱為硬鏈結 hard link 另一種被稱為符號鏈結 symbolic link 預設情況下,ln命令產生硬鏈結。硬連線 硬連線指通過索引節點來進行連線。在linux的檔案系統中,儲存在磁碟分割槽中的檔案不管是什麼型別都給它分配乙個編號,稱為索引節點號...

linux下軟連線和硬鏈結的建立

ln 建立鏈結 命令格式 ln option sourcefile distfile 選項 f 建立時,將同檔名刪除。i 刪除前進行詢問。建立軟連線和硬連線 ln s source dist 建立軟連線 ln source dist 建立硬連線 軟連線和硬連線可以這樣理解 連線有軟連線和硬連線之分。...

Linux下連線SSH伺服器

編譯安裝obfuscated openssh步驟如下,不同發行版本略有不同,僅供參考 wget o ofcssh.tar.gz tar zxvf ofcssh.tar.gz cd brl obfuscated openssh ca93a2c configure 如果有不滿足的依賴,需要安裝相應的包,...