寫動態庫時遇到了symbol lookup error問題


之前寫TLPI上的代碼一直是手動進行錯誤處理,感覺代碼冗余量很大,最后還是決定使用書上的tlph_hdr.h,順便回顧下動態庫的創建/使用。

參考很久之前的一篇博客 linux上靜態庫和動態庫的編譯和使用

但是感覺這篇博客寫了后我一直沒真正用過動態庫,於是花了些時間復習下,結果倒好,一直出問題。

xyz@ubuntu:~/lib$ ls
a.out  f.c  g.c  h.c  libutil.so  main.c  util.h

f.c g.c h.c分別是3個函數f()、g()、h()的定義,util.h是這3個函數的聲明,main.c包含了util.h,並在main()函數中調用了這3個函數。

a.out則是成功生成的程序,生成過程如下

xyz@ubuntu:~/lib$ gcc f.c g.c h.c -fpic -shared -o libutil.so
xyz@ubuntu:~/lib$ gcc main.c -L. -lutil

第一步編譯了3份包含函數具體實現的源文件,第二步編譯了主程序。

其中-L.將當前目錄設為動態庫查找位置,-lutil代表查找的動態庫為libutil.so,這只是語法糖,這句命令用libutil.so替換-lutil也可以。

最后運行a.out時報錯

./a.out: symbol lookup error: ./a.out: undefined symbol: f

自己瞎折騰半天不知道原因,起初懷疑動態庫生成錯誤,沒有包含3個函數,但是命令並沒錯。最后還是動用搜索引擎,試着用ldd(1)來查看程序依賴庫(ldd的使用在TLPI的第3章 3.3中查找glibc共享庫的位置時也使用過)

xyz@ubuntu:~/lib$ ldd a.out 
    linux-vdso.so.1 =>  (0x00007fff509eb000)
    libutil.so => /usr/lib/x86_64-linux-gnu/libutil.so (0x00007f1a9e581000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1a9e1b7000)
    /lib64/ld-linux-x86-64.so.2 (0x000055fcfc069000)

原因出來了,系統自帶了一個libutil.so,我自定義的動態庫和它重名了,由於動態庫是優先查找系統路徑(再其次是-L后面的路徑,在這里是當前目錄),系統自帶的libutil.so自然不會有f() g() h()這三個函數,因此f()被認為是未定義的符號,即找不到函數f()的具體定義。

只要改個名字就行了,然后就遇到了下面錯誤

xyz@ubuntu:~/lib$ gcc f.c g.c h.c -fpic -shared -o libfgh.so
xyz@ubuntu:~/lib$ gcc main.c -L. -lfgh
xyz@ubuntu:~/lib$ ./a.out 
./a.out: error while loading shared libraries: libfgh.so: cannot open shared object file: No such file or directory

最好的解決方式還是把動態庫目錄加到環境變量里,而不是把動態庫隨便扔個系統目錄。

xyz@ubuntu:~/lib$ export LD_LIBRARY_PATH=$(pwd)
xyz@ubuntu:~/lib$ echo $LD_LIBRARY_PATH 
/home/xyz/lib
xyz@ubuntu:~/lib$ ./a.out 
f()
g()
h()

運行成功,然而這個環境變量重啟后就沒了,所以需要把它添加到在~/.bashrc末尾,此時就需要把當前目錄用絕對路徑表示了

export LD_LIBRARY_PATH=/home/xyz/lib 

這樣系統重啟之后便仍可運行a.out,如果需要通知系統.bashrc文件已更新,可用命令source ~/.bashrc


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM