鏈結時庫檔案沒有放在命令列尾部所造成的問題

2021-09-11 18:41:34 字數 2225 閱讀 9120

需要說明下所有提示未定義的函式都是在動態庫libitcastsocket.so和libmessagereal.so這兩個動態庫之中的,這些函式是在mngclient_agree中使用的。上面三個.o檔案是根據原始檔編譯好的,都沒有問題。然後我使用以下命令想將三個.o的檔案鏈結成可執行目標檔案。

gcc -l/home/project/day01/secmngsever_secmngclient_linux/lib  -lpthread -litcastsocket -lmessagereal keymngclient.o keymnglog.o keymngclientop.o -o keymngclient
上面的命令,我仔細檢查了所用的動態庫的路徑和動態庫名,都沒有錯誤。但是還是出現了上圖中的未定義錯誤。按道理來說,動態庫都能找到,鏈結的時候是能夠對使用的動態庫函式完成符號解析的。可為什麼會出錯呢?最後發現原來是使用gcc命令的時候,把指定動態庫放在了.o檔案之前導致的。把指定動態庫放到後面就行了,如下:

gcc -l/home/project/day01/secmngsever_secmngclient_linux/lib keymngclient.o keymnglog.o keymngclientop.o -lpthread -litcastsocket -lmessagereal  -o keymngclient
2、將庫檔案放在前面出現未定義的原因:linux鏈結器在符號解析階段是按照從左向右的順序掃瞄命令列的。當動態庫沒有放在命令列的尾部時,可能出現先掃瞄動態庫,後掃瞄原始檔的情況。這時候在後掃瞄原始檔的時候就不會檢查前面的動態庫是否定義了該原始檔使用過的符號,從而導致出現未定義的錯誤。就上面的例子來說,就是keymngclientop.o中的mngclient_agree函式中使用了動態庫libmessagereal.so和libitcastsocket.so的函式,而鏈結的時候將keymngclientop.o放在了在這兩個動態庫之後,那麼最後解析keymngclientop.o中的符號時,就會發現率屬於動態庫libmessagereal.so和libitcastsocket.so的函式沒有定義,因為不會搜尋前面的檔案是否有符號的定義。所以一般都是將庫放在命令列的末尾。

從3中我們可以知道,靜態鏈結庫編譯的時侯會鏈結到可執行檔案之中。而動態鏈結庫不會鏈結到可執行檔案之中,所以編譯之後是部分鏈結的可執行目標檔案。在部分鏈結的時候需要指定鏈結的動態庫的路徑和動態庫名,雖然不鏈結進可執行目標檔案,但是需要從動態庫中查詢可重定位目標檔案中的外部符號,從而保證整個編譯過程通過。對應於圖中的1。

對於圖中的2,載入器載入和執行了prog21之後,發現在可執行檔案的.interp節包含了動態鏈結器的路徑名,從而載入和執行這個動態鏈結器。此時,動態鏈結器會執行下面的重定位完成鏈結任務。

總結來說就是,對於動態庫,靜態鏈結階段只完成對動態庫的符號解析(圖中1),從而將引用的動態庫中的全域性符號儲存在符號表中。而重定位是在執行部分鏈結可執行目標檔案的時候呼叫動態鏈結器完成的(圖中2)。

對於elf格式的可執行檔案,是由動態鏈結器ld-linux.so來完成可執行檔案內部使用的庫檔案的呼叫操作的。ld-linux.so需要知道所呼叫的庫檔案所在的路徑,一般會先搜尋可執行檔案內部的dt_rpath段(包含了可執行檔案所呼叫庫的路徑),然後再搜尋環境變數ld_library_path(環境變數的值也是路徑),再搜尋/etc/ld.so.cache檔案列表,最後搜尋/lib、/usr/lib目錄找到庫檔案載入記憶體。

可以使用ldd命令來檢視

ld-linux.so呼叫資訊,如下:

如果使用ldd命令發現有動態庫找不到,可以將動態庫的路徑新增到ld_library_path中。

==》對於鏈結靜態庫和動態庫可以參控《深入理解計算機系統》7.6.3節和7.10節。

U盤讀取檔案時發現損壞,命令列修復

這是我今天準備清理u盤的時候發現u盤好多檔案出現這種損毀,後來知道是之前親戚家小孩在我穿檔案的時候插拔u盤了,emmm在網上查詢了一下方法大部分都是推薦用系統的自己的u盤修復 1.win r 2.輸入cmd 3.輸入chkdsk f 你u盤在你電腦裡的碟符,例如 chkdsk f d 就是檢查d盤檔...

U盤讀取檔案時發現損壞,命令列修復

這是我今天準備清理u盤的時候發現u盤好多檔案出現這種損毀,後來知道是之前親戚家小孩在我穿檔案的時候插拔u盤了,emmm在網上查詢了一下方法大部分都是推薦用系統的自己的u盤修復 1.win r 2.輸入cmd 3.輸入chkdsk f 你u盤在你電腦裡的碟符,例如 chkdsk f d 就是檢查d盤檔...

命令列匯入匯出資料庫檔案

匯出資料庫全部資料 cmd 開啟命令列視窗 sqlplus 進入oracle 使用者名稱 輸入要匯出的資料庫使用者名稱 密碼 輸入要匯出的資料庫密碼 exp file d 檔名.dmp.執行命令 是開始匯入匯出的前置符號,file是你要存放到的地方 然後按enter鍵執行,按照提示在輸入一遍資料庫的...