1. 程式人生 > >動態庫連結踩坑記

動態庫連結踩坑記

問題

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

原因

對於生產環境出現問題的可執行檔案A,執行命令 nm A 發現的確存在著報錯的時候的函式有著標誌U(表明該函式未定義),可此函式在可執行檔案A中並沒有任何的宣告,這隻能說明,該函式是來自於第三方的庫檔案,經過檢查發現,的確存在了一個動態庫檔案中使用了此函式。同樣的使用命令 nm A 檢視發現該函式同樣在該動態庫中未定義。
起初,我們認為是別人提供的這個動態庫.so不正確,因此,我們重新編譯了這個動態庫後,再重新放入生成環境,再次執行,同樣的錯誤繼續出現。這時候,很自然而然的我們懷疑到了應該是編譯動態庫的make檔案出現了錯誤。
在仔細認真的檢查後make檔案後,發現在編譯形成動態庫時,其最終形成目標集的命令類似下面的命令

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

解決

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

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

總結

對於一個後端工程師來說,編譯、連結、ELF檔案是一項必不可少的知識,這裡給出一些常用的命令,這些命令都可以幫助大家在碰到此類問題時候不會兩眼一抹黑。具體的用法,去man一下吧。

ldd –檢視可執行檔案連結那些動態庫
nm –檢視可執行檔案,庫檔案符號表
readelf –檢視elf檔案的檔案資訊
objdump –顯示目標檔案的資訊

相關推薦

動態連結

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

IOS和安卓共用一個二維碼,實現掃碼跳轉連結-_04

ios和安卓共用一個二維碼,實現掃碼跳轉連結 直接上程式碼了 也是參考了網上的demo,直接小修改了一下。臨時接了一個任務,直接套過來了。因為安卓微信的內建的瀏覽器和手機自帶的不一樣,在ios上面沒有問題,會直接提示跳轉到appstore。要求是實現安卓微信跳轉顯示

[轉]Spark :數據(Hbase+Mysql)

cep 直接 策略 https rds 但是 更新 base ID https://cloud.tencent.com/developer/article/1004820 Spark 踩坑記:數據庫(Hbase+Mysql) 前言 在使用Spark Streaming的過程

RISC-V----__builtin_clz((x)函式的應用

  RISC-V的確是個好東西,可是,免費的東西往往需要付出代價才能得到了,最近遇到了一個演算法中的問題,追了好久,最終追到了這個庫函式中,沒想到,這個庫函式居然還隱藏著一些貓膩。值得記下來啊。 首先上一個在X86平臺下的例子:    1 #include <stdio.h>

Visual Studio For MacOS (二)

mirrors class app macosx andro mce 資料 library devel Visual Studio For MacOS安裝安卓SDK。 系統默認安裝了安卓6.0 API23的SDK。 但是我需要安卓7.0的,API24. 遂安裝。

spark共享變量

park oid and 共享變量 roi syn out his andro %E5%9C%A8android%E4%B8%AD%E6%80%8E%E4%B9%88%E7%94%A8this removeviewinlayout?к????? repo????л???

Linux使用

gre 16px -- 機器 操作 onf 問題: 失敗 gbk Ubuntu安裝坑: 1、對於新手第一次安裝ubuntu,特殊情況會出現因為分辨率問題導致安裝界面不全,無法進行下一步操作。 解決方案:使用alt+鼠標左鍵拖動屏幕Linux文件名亂碼問題:

java-getResourceAsStream

mov load color () tar type 當前 blog ase 本文主要是研究下面集中方法到底誰才能真正的load到文件,你能一眼看出來嗎? GetResourcesSample.class.getClassLoader.getResourceAsStream

c# 重載運算符(ovveride operator),關於null比對

漏洞 pre console blog 為什麽 留言 報表 bool 解決辦法 場景描述: 需要比對兩個版本的對應對象是否完全一致(每個屬性值一致),不一致的導出報表顏色標識,以便提醒後續使用報表人員。 實現思路: 對象重載ToString方法,另實現一比對基類(為了通用)

Spring @Transactional

然而 效果 記錄 dcl iso 如果 分庫分表 ignore mar @Transactional踩坑記 總述 ? Spring在1.2引入@Transactional註解, 該註解的引入使得我們可以簡單地通過在方法或者類上添加@Transactional註解,實現事務控

桌面應用“標註器”打包

環境 的確 變量 標註 imp sci 技術 報錯 編寫 昨天(2018/4/6)花了幾乎一天的時間打包我的桌面應用“標註器”。下午3點完成最後的編寫之後,準備在女朋友雅喻的電腦上配環境打包(我的電腦不能用pyinstaller打包,重裝也不行,玄學錯誤。)。雅喻的電腦上缺

uWSGI

dex wsgi oba 啟動 監聽 head HR nvi header 一、協議的一致性 uWSGI 是在 nginx 後面,所以 nginx 轉發請求時的協議要和 uWSGI 監聽的協議一致。否則就會出現問題,因為是三者之間的通信,排查起來需要想清楚請求傳遞的次序:

Vue項目~

found 成功 原因 提示 數據文件 support then ror tro 最近在寫一個Vue的項目~踩了很多坑,下面總結一下出現的問題 1.空白頁面,不提示報錯,但是什麽都沒有 main.js const app = new Vue({ router }).$

create-react-app

tcs onf class working zip als mpi iconfont hat 前言 哇,不的不說這個react 這個腳手架create-react-app腳確實有很多問題,哈哈,下面來看看吧有哪些坑: 引用sass或者less 記得16

.NetCore SignalR

cred this arp 虛擬機 user fault new alt dem 背景 由於最近公司要做微信小程序聊天,所以.NetFramwork版本的SignalR版本的不能用了。因為小程序裏沒有windows對象,導致JQuery無法使用。而Signalr的 js客戶

Win10 安裝配置 MongoDB 4.0

repl 其他 文件夾 power chm font 無人值守安裝 path .org redis 官方沒有 Windows 版的,微軟維護的已經好久沒更新了,所以就在想著換成 MongoDB。 於是一趟被我復雜化的踩坑之旅就開始了,同時也記錄一下,避免有人遇見跟我一樣的

微信公眾號支付

系統 shm efi bsp 網絡異常 router nec 平臺 wiki   前兩周做微信H5支付,在瀏覽器端用的,天真地以為app掛到公眾號中也能用,結果不行>"<|||| ,只好再對接一次公眾號支付,微信的支付對接下來總體感覺就是封裝地不如支付寶,文檔不

Springcloud---使用feignclient遠端呼叫服務404

公司專案進行微服務改造,由之前的dubbo改用SpringCloud,微服務之間通過FeignClient進行呼叫,今天在測試的時候,eureka註冊中心有相應的服務,但feignclient就是無法調通,一直報404錯誤,排查過程如下: 一、問題:   服務提供方定義的介面如下: /** *

vlc-android 編譯

VLC-Android編譯踩過的坑及感悟,整理髮表出來,希望對大家有幫助。 一、建議掌握的基本知識【否則在編譯過程中,連錯誤都不知道怎麼查,如下一些基本點是針對linux小白的,大牛勿噴】 a. Makefile的工作原理,明白Rule-Target-Prerequisites-Reci

mpvue

node --versionnpm --versionvue -V 微信開發者工具:開發、除錯和模擬執行微信小程式的最核心的工具了,所以必須安裝 # 全域性安裝 vue-cli $ npm install --global vue-cli # 建立一個基於 mpvue-quickstart 模