動態庫鏈結踩坑記

2021-08-19 22:46:30 字數 1300 閱讀 9404

最近,在一系列的編寫**、編譯、正確的形成可執行檔案後,將可執行檔案執行在生成環境時,出現了應該是在編譯鏈結時最常見的錯誤:symbol not defined。下面,將會逐一的從問題是如何產生,以及如何解決進行說明,就當做是自我的乙個問題記錄。

對於生產環境出現問題的可執行檔案a,執行命令nm a發現的確存在著報錯的時候的函式有著標誌u(表明該函式未定義),可此函式在可執行檔案a中並沒有任何的宣告,這只能說明,該函式是來自於第三方的庫檔案,經過檢查發現,的確存在了乙個動態庫檔案中使用了此函式。同樣的使用命令nm a檢視發現該函式同樣在該動態庫中未定義。

起初,我們認為是別人提供的這個動態庫.so不正確,因此,我們重新編譯了這個動態庫後,再重新放入生成環境,再次執行,同樣的錯誤繼續出現。這時候,很自然而然的我們懷疑到了應該是編譯動態庫的make檔案出現了錯誤。

在仔細認真的檢查後make檔案後,發現在編譯形成動態庫時,其最終形成目標集的命令類似下面的命令

> gcc -shared -fpic lib***.a ***x.o -o lib***x.so

如果認真的看,會發現該動態庫還鏈結了乙個其他的靜態庫,而那個未定義符號函式正是在這個靜態庫中宣告定義的。很明顯,在編譯動態庫的時候,由於採用gcc的編譯器的版本查詢符號是從前向後進行查詢,而.o檔案引用了前面.a檔案,因此,.o檔案並沒有真正的鏈結到正確的函式符號。而在這個過程中,也並沒有報告錯誤,而是順利的產生了動態庫檔案,這也就間接的導致了上述問題的發生。

在gcc編譯動態庫的時候,即使出現了符號未正確的鏈結的情況,鏈結器也只是跳過該錯誤進行執行,這是由於gcc為了某種原因允許了這種情況(具體的原因,大家可以上網查閱,在此就不贅述了),因此,gcc編譯器提供了下面的一些引數用於告知鏈結器對此種情況進行錯誤報告(很多的類似引數,區別建議大家去查閱gcc的編譯手冊)

-wl,–no-undefined

-wl,–unresolved-symbols=ignore-in-shared-libs

至此,解決上述的問題,我們可以將靜態庫檔案和目標檔案換個位置便可解決,但是我們還是建議大家在編譯動態庫的時候加入上述的引數,避免此類問題的出現。

ldd –檢視可執行檔案鏈結那些動態庫

nm –檢視可執行檔案,庫檔案符號表

readelf –檢視elf檔案的檔案資訊

objdump –顯示目標檔案的資訊

mybatis LocalCache踩坑記錄

上週週三下午,準備去吃飯的時候,值班突然找過來說使用者操作時爆出訂單不存在的問題,因為之前做了分表連續很長一段時間都沒問題,而且當時找過來的都是一些因為產品或者qa操作不當找不到記錄的情況,就沒有在意這些,當時以為幾分鐘就能搞定,但是沒想到居然是線上日誌爆出的問題,經過驗證訂單確實不存在!心想完了,...

Linux生成動態鏈結庫 so檔案的踩坑

期望在linux環境下執行r語言呼叫c語言的專案,首先要將所有c檔案編譯成動態鏈結庫.so檔案 r user r cmd shlib test1.c test2.c test3.c遇到的問題 1.make no rule to make target test2.o needed by test2....

AdMob接入踩坑記

首先列出參考文件 admob官方參考鏈結 我是cocos2d x v3.9的工程,在按照官方文件接入之後,出現一堆編譯錯誤例如 plain view plain copy undefined symbols for architecture arm64 objc class glkview refe...