為什麼 -r 選項(可重定位)會導致 ld 找不到任何庫?
介紹
在程式設計和計算機科學的世界裡,有各種各樣的技術和工具被用來解決各種問題。程式設計師遇到的一個常見問題是連結錯誤。當程式被編譯和連結時,它必須找到必要的庫才能執行。然而,有時連結器無法找到所需的庫,從而導致連結錯誤。在本文中,我們將討論為什麼 -r 選項(可重定位)會導致 ld 找不到任何庫,並提供示例。
什麼是 -r 選項?
-r 選項是與 GNU 連結器 ld 一起使用的命令列選項。該選項指定連結器的輸出應該是一個可重定位的目標檔案,它是一個可以進一步連結以建立可執行檔案或共享物件檔案的檔案。-r 選項通常用於將目標檔案連結起來以建立靜態庫。當使用 -r 選項時,連結器不會解析目標檔案中的所有未定義符號,並且輸出是一個可重定位的目標檔案,可用於以後的進一步連結。
為什麼 -r 選項會導致 ld 找不到任何庫?
當使用 -r 選項時,ld 不會查詢任何庫,因為它假設所有必要的符號都在輸入目標檔案中定義。這意味著,如果存在任何未定義的符號,ld 將無法在任何庫中找到它們,從而導致連結錯誤。
示例
為了更好地理解為什麼 -r 選項會導致 ld 找不到任何庫,讓我們考慮一個示例。假設我們有兩個目標檔案 a.o 和 b.o,我們希望將它們連結起來以建立一個靜態庫。這兩個目標檔案包含一些需要解析的未定義符號。
如果我們使用以下命令連結目標檔案:
$ ld -r a.o b.o -o libab.o
輸出將是一個可重定位的目標檔案 libab.o,可用於以後的進一步連結。但是,如果我們嘗試連結 libab.o 以建立可執行檔案,我們將收到一個連結錯誤,因為目標檔案中的未定義符號未得到解析。
$ ld libab.o -o myprog
未定義符號:_foo _bar
在這種情況下,ld 未找到包含 _foo 和 _bar 符號的任何庫,導致連結錯誤。
解決方案
為了解決由 -r 選項引起的連結錯誤,我們需要顯式地連結必要的庫。這意味著我們需要使用 -l 選項來指定包含未定義符號的庫。
例如,如果目標檔案中的未定義符號在 libmylib.a 庫中定義,我們可以如下連結目標檔案和庫:
$ ld -r a.o b.o -lmylib -o libab.o
這將連結目標檔案和庫以建立一個可重定位的目標檔案 libab.o,可用於以後的進一步連結。
其他資訊
-r 選項在建立靜態庫時很有用,因為它允許我們建立一個可用於建立多個靜態庫的中間目標檔案。這節省了時間並減少了冗餘,因為我們不必每次想要建立靜態庫時都重新編譯目標檔案。
-r 選項也可用於建立可重定位的共享庫。共享庫是在執行時載入到記憶體中的庫,可以由多個程式共享。在建立共享庫時,我們可以使用 -r 選項建立一箇中間可重定位的目標檔案,該檔案可以與其他目標檔案和共享庫連結以建立共享庫。
需要注意的是,-r 選項不會阻止 ld 在建立可執行檔案或共享庫時搜尋庫。該選項僅影響連結器在建立可重定位目標檔案時的行為。
結論
總之,-r 選項會導致 ld 找不到任何庫,因為它假設所有必要的符號都在輸入目標檔案中定義。如果存在任何未在輸入檔案中定義的未定義符號,這可能會導致連結錯誤。為了解決連結錯誤,我們需要使用 -l 選項顯式地連結必要的庫。瞭解 -r 選項的工作原理以及如何解決由該選項引起的連結錯誤對於希望建立靜態庫和可執行檔案的程式設計師來說非常重要。