問題描述
項目中準備引入redis,采用acl的c++庫對redis進行通路。acl的示例代碼如下所示
#include
對示例代碼進行編譯連結
`
報了許多連結的錯誤
(aio_listen_stream.o
問題分析
acl和acl_cpp均為靜态庫,acl是最基礎的庫,以C語言實作,其它庫均依賴于該庫; acl_cpp庫用C++封裝了acl庫,提供給C++程式調用。
連結錯誤集中表現為acl_cpp庫引用了acl庫中的函數但未能找到其定義。
問題解決
在編譯指令的參數中已給出了acl庫的路徑和名稱,不應該找不到。嘗試把acl_cpp庫在指令行中的順序放在acl庫之前
`
順利編譯通過。
原理探究
建立一個示例工程,包含main.c、comp1_func1.c、comp1_func2.c、comp2_func1.c四個檔案,其函數調用關系如下所示:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iM2UzMzkDZzImM3QTMlZzYwUDNjFGZ0QGOyIjYwMzMl9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
- 編譯main.c
0000000000000000 *UND*
main.o中有兩個未定義的符号:comp1_func1和comp2_func1
- 編譯靜态庫
0000000000000000 g F .text 000000000000000e comp1_func1
comp1_func2.o: 檔案格式 elf64-x86-64
libcomp2.a中有一個未定義的符号comp1_func2
- 增量連結 将main.o和libcomp1.a先進行連結
0000000000000000 l df *ABS*
連結器并不是把靜态庫檔案看做一個整體,而是将打包在其中的目标檔案(.o)作為連結單元。在連結過程中,如果某個目标檔案中的符号被用到了,那麼這個目标檔案會單獨從庫檔案中提取出來并入可執行程式,而其餘的目标檔案則會被丢棄。
main.o中引用了libcomp1.a中comp1_func1.o的comp1_func1函數,是以将comp1_func1.o并入,而comp1_func2.o中的comp1_func2函數未被引用,是以被丢棄。
- 全量連結 将main.o和libcomp1.a、libcomp2.a進行連結
0000000000000000 *UND*
libcomp2.a中引用的comp1_func2函數雖然已在libcomp1.a中定義,但由于comp1_func2.o被丢棄,導緻該函數找不到定義
0000000000000021 g F .text 000000000000000e comp1_func1
整個分析的過程可參考下圖:
将靜态庫的順序調換後,所有符号都找到了定義。是以在連結靜态庫的時候,應該将被依賴的庫放在最右邊。