運行編譯後的程式報錯 error while loading shared libraries: lib*.so: cannot open shared object file: No such file or directory 首先說明一下,這個題目有點長,但是卻很好地反應了遇到的問題點。 在《 ...
運行編譯後的程式報錯 error while loading shared libraries: lib*.so: cannot open shared object file: No such file or directory
-------------------------------------------------------------------------------------------------------------------------------------------------
首先說明一下,這個題目有點長,但是卻很好地反應了遇到的問題點。
在《如何用C代碼生成二維碼》一文中,小編也向大家展示了在正確無誤地編譯好qrcode_test程式後,運行報錯的問題。這次我們再拿出來說一說。
當時在終端手動./運行程式報錯的提示 ./qrcode_test: error while loading shared libraries: libzint.so.2.4: cannot open shared object file: No such file or directory
大概的意思就是在運行程式的時候,沒有找到程式所需的libzint.so動態庫。大家都知道,動態庫與靜態庫的最大區別就是:靜態庫是靜態鏈接,也就是在生產可執行文件的時候就把靜態庫中的實現嵌入到程式中了,一旦編譯成功了,靜態庫也就有存在的價值了,即便靜態庫不存在了,可執行程式也是可以跑起來的;但是動態庫就不一樣了,它是遵循動態鏈接,也是就說編譯的時候需要指定路徑去找該so文件鏈接編譯,運行的時候也需要指定相應的路徑去找。如果在運行的時候,可執行程式會先去預設的系統lib目錄下,尋找該so,如果找不到了,就該報錯了:error while loading shared libraries。(可以通過該文章,瞭解下動態庫的動態載入機制 http://blog.csdn.net/dbzhang800/article/details/6918413)
上面這一段話,講可執行程式運行時去找so文件,講得比較籠統,以下總結以下:
動態庫的搜索路徑搜索的先後順序是:
1.編譯目標代碼時指定的動態庫搜索路徑;
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參數得是正確的。這個方法,尤其是在交叉編譯嵌入式設備的可執行程式時,十分有用。不妨讀者可以自己試試看。