運行編譯後的程序報錯 error while loading shared libraries: lib*.so: cannot open shared object file: No such file or directoryhtml
------------------------------------------------------------------------------------------------------------------------------------------------- linux
首先說明一下,這個題目有點長,可是卻很好地反應了遇到的問題點。spa
在《如何用C代碼生成二維碼》一文中,小編也向你們展現了在正確無誤地編譯好qrcode_test程序後,運行報錯的問題。此次咱們再拿出來講一說。.net
當時在終端手動./運行程序報錯的提示 ./qrcode_test: error while loading shared libraries: libzint.so.2.4: cannot open shared object file: No such file or directorycode
大概的意思就是在運行程序的時候,沒有找到程序所需的libzint.so動態庫。你們都知道,動態庫與靜態庫的最大區別就是:靜態庫是靜態連接,也就是在生產可執行文件的時候就把靜態庫中的實現嵌入到程序中了,一旦編譯成功了,靜態庫也就有存在的價值了,即使靜態庫不存在了,可執行程序也是能夠跑起來的;可是動態庫就不同了,它是遵循動態連接,也是就說編譯的時候須要指定路徑去找該so文件連接編譯,運行的時候也須要指定相應的路徑去找。若是在運行的時候,可執行程序會先去默認的系統lib目錄下,尋找該so,若是找不到了,就該報錯了:error while loading shared libraries。(能夠經過該文章,瞭解下動態庫的動態加載機制 http://blog.csdn.net/dbzhang800/article/details/6918413)htm
上面這一段話,講可執行程序運行時去找so文件,講得比較籠統,如下總結如下:blog
動態庫的搜索路徑搜索的前後順序是: get
1.編譯目標代碼時指定的動態庫搜索路徑;io
2.環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑; 編譯
3.配置文件/etc/ld.so.conf中指定的動態庫搜索路徑;
4.默認的動態庫搜索路徑/lib /usr/lib。
可參考下這篇博文,它裏面說起了gcc編譯動態庫和運行連接動態庫的知識。http://www.cnblogs.com/zhengmeifu/archive/2010/03/02/linux-gcc_compile_header_file_and_lib_path.html
回到可執行程序運行報error while loading shared libraries錯的問題上來,在《如何用C代碼生成二維碼》一文中,也講到了如何避過這種錯誤而將程序跑起來,咱們使用的是上面說起的「2.環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑;」,即經過設置LD_LIBRARY_PATH,把當前程序使用的so的路徑添加到LD_LIBRARY_PATH中去,這樣程序跑起來的時候,去LD_LIBRARY_PATH找確定就能夠找到該so了。固然以前咱們也已經驗證了此方法的正確性。
看,程序運行就沒有問題。
若是僅僅又是重複介紹該方法,那麼此文存在的意義就不大了。此文最大的意義在於,告訴讀者,咱們能夠不用設置LD_LIBRARY_PAT,也同樣能夠把程序跑起來,那麼咱們該從那裏下手呢?本文主要介紹,從編譯該程序開始。
這裏就要先介紹下gcc的編譯選項了,但這裏不具體細說,有興趣能夠經過man gcc去了解,或者從博文的上一篇文章 【轉載】gcc 使用中經常使用的參數及命令http://www.cnblogs.com/Recan/p/6012248.html 去了解。
這裏,咱們須要用到的編譯選項是-Wl,-rpath;主要這裏是字母l,而不是數字1。-rpath選項就是告訴gcc在編譯連接的時候,把該程序的運行是查找so的路徑寫入到ELF文件中。使用方法就是 gcc –o OutApp *.c –lzint –Wl,-rpath=」/usr/local/lib」或gcc –o OutApp *.c –lzint –Wl,-rpath –Wl,「/usr/local/lib」二者在功能是等價的。以下圖所示:
從圖中咱們可看到,確實編譯成功後直接運行程序就不會再報error while loading shared libraries了,並且這種方法最大的好處就是,在編譯成功後,不用再去作任何設置就能夠把程序跑起來了,固然是編譯時傳遞的-rpath參數得是正確的。這個方法,尤爲是在交叉編譯嵌入式設備的可執行程序時,十分有用。不妨讀者能夠本身試試看。