Linux下使用nm命令排查和解決“undefined reference to ”
一、案例
編譯出一個動態庫.libXXXEngine.so。然後直接在另一個工程中,把標頭檔案include進來,並link到該庫:-lXXXEngine.
嘗試編譯,出錯:
.//libXXXEngine.so:undefined reference to`CHttpParser::GetCurrentHttpMethod(http_method_t&)'
.//libGenaEngine.so: undefined reference to `CHttpParser::CHttpParser(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
.//libGenaEngine.so: undefined reference to `CHttpParser::ExactResultFromHttpMsgBody(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
.//libGenaEngine.so: undefined reference to `CHttpParser::parse(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
從描述上看,以下四個函式沒有定義:
(1) CHttpParser::GetCurrentHttpMethod(http_method_t&)
(2)CHttpParser::CHttpParser(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)
(3)CHttpParser::ExactResultFromHttpMsgBody(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
(4)CHttpParser::parse(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)
然而奇怪的是,當我跟進libXXXengine.so的具體程式碼時,卻發現標頭檔案和原始檔的定義和宣告都可以找到。那麼究竟什麼原因呢?
二 問題分析
出現這種錯誤,有幾個原因:
(1)一是使用者自己定義的函式或者全域性變數所在原始碼檔案,沒有被編譯、連線。
(2)一是使用者自己定義的函式或者全域性變數沒有定義。
(3) 未定義的符號是一個動態庫函式,在源程式中使用了該庫函式,而連線過程中還沒有給定相應的函式庫的名稱,或者是該檔案庫的目錄名稱有問題.
即:.so檔案沒有把所有需要的庫都連結上。使用了庫中定義的實體,但沒有指定庫(-lXXX)或者沒有指定庫路徑(-LYYY),會導致該錯誤,
(4)C/C++相互依賴和連結
gcc和g++編譯結果的混用需要保證能夠extern "C" 兩邊都可以使用的介面,在我們的64位環境中gcc連結g++的庫還需要加上 -lstdc++。
經排查,我們在makefile中通過-lXXEngine正確連結了libXXXEngine.so,同時,我們也把相應的標頭檔案放到我當前工程目錄下了。然而,被告知且出錯的函式都是在動態庫中的。好奇怪!
為了進一步找到問題的root cause,我們使用了nm命令來進一步排查:
nm libXXXEngine.so |grep CHttpParser
U _ZN11CHttpParser20GetCurrentHttpMethodER13http_method_t
U _ZN11CHttpParser26ExactResultFromHttpMsgBodyESsRSs
U _ZN11CHttpParser5parseESs
U _ZN11CHttpParserC1ESs
00000000000134e6 W _ZN5boost10shared_ptrI11CHttpParserE4swapERS2_
0000000000012e56 W _ZN5boost10shared_ptrI11CHttpParserEC1ERKS2_
0000000000012e30 W _ZN5boost10shared_ptrI11CHttpParserEC1Ev
0000000000014cda W _ZN5boost10shared_ptrI11CHttpParserEC1IS1_EEPT_
0000000000012cda W _ZN5boost10shared_ptrI11CHttpParserED1Ev
0000000000013df4 W _ZN5boost10shared_ptrI11CHttpParserEaSERKS2_
000000000001348b W _ZN5boost14checked_deleteI11CHttpParserEEvPT_
0000000000014c4c W _ZN5boost6detail12shared_countC1I11CHttpParserEEPT_
0000000000013bae W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserE11get_deleterERKSt9type_info
0000000000013b92 W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserE7disposeEv
0000000000013452 W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserEC1EPS2_
0000000000014d1e W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserED0Ev
0000000000014d5a W _ZN5boost6detail17sp_counted_impl_pI11CHttpParserED1Ev
000000000001591c W _ZNK5boost10shared_ptrI11CHttpParserEptEv
00000000000134b4 W _ZSt4swapIP11CHttpParserEvRT_S3_
000000000021ba40 V _ZTIN5boost6detail17sp_counted_impl_pI11CHttpParserEE
0000000000017420 V _ZTSN5boost6detail17sp_counted_impl_pI11CHttpParserEE
000000000021ba00 V _ZTVN5boost6detail17sp_counted_impl_pI11CHttpParserEE
0000000000017100 r _ZZNK5boost10shared_ptrI11CHttpParserEptEvE19__PRETTY_FUNCTION__
命令輸出結果顯示,那些報錯的函式的符號 同樣可以在nm裡找到。
不同的是,這四個出錯的函式,輸出的前半部分為空。
這就是異常和問題所在!
下面我們只要對nm命令稍作了解:
nm命令還是比較簡單而且強大的。它用來列出一個目標檔案中的各種符號。符號的種類很多,以下是一些常見的符號型別
nm輸出字元 | 含義 |
R | Read only symbol. 比如在程式碼中有一個const MAXDATA = 3095; 則MAXDATA就是一個Read only symbol |
N | 這是一個除錯符號 |
D | 這是一個已經初始化的變數的符號。比如程式碼中int i = 1和char *str = "Hello"則i和str都是這種型別的符號 |
T | Text段的符號。子程式都是這種符號,比如檔案中實現了一個函式function,則function就是這種符號 |
U | 未定義的符號。如果檔案中引用了不存在的函式,則這些未定義的函式符號就是這種型別 |
S | 未初始化的符號,比如全域性變數int s;則s的符號就是此型別 |
至此,我們可以推斷:動態庫中有未定義的符號,說明該動態庫的編譯有問題,即是如下原因之一:
(1)一是使用者自己定義的函式或者全域性變數所在原始碼檔案,沒有被編譯、連線。
(2)一是使用者自己定義的函式或者全域性變數沒有定義。
這種問題的解決,首先就要檢查動態庫的makefile寫的是否有問題。
果然,發現makefile裡沒有把該出錯函式所在的定義的原始檔沒有編譯進去。
三 問題解決
找到了原因,問題解決就方便了。修改.so的makefile即可。
svn diff
-COM_SRCS := $(GENASRCDIR)/CGenaEngine.cpp
+COM_SRCS := $(GENASRCDIR)/CGenaEngine.cpp $(HTTPSRCDIR)/CHttpMiniParser.cpp -----》把CHttpMiniParser.cpp 編譯進去。
相關文章
- undefined reference toUndefined
- "undefined reference to" 問題解決方法Undefined
- Qt undefined reference to ***QTUndefined
- undefined reference to `__isnanf'UndefinedNaN
- linux下的庫操作命令ar, nmLinux
- undefined reference to錯誤的解決方法Undefined
- sphinx :undefined reference to `libiconv' 報錯解決辦法Undefined
- Linux make編譯報錯:undefined reference to `vtable for XXX 'Linux編譯Undefined
- Qt 訊號發射部分 undefined reference to錯誤QTUndefined
- codeblocks處理undefined reference to `pthread_create'BloCUndefinedthread
- Linux下scp命令使用Linux
- linux壓縮和解壓縮命令Linux
- 排查和解決 CentOS 伺服器磁碟空間不足問題CentOS伺服器
- C++:與C混合程式設計 CMake undefined reference toC++程式設計Undefined
- linux下nc命令的使用Linux
- 在 Linux 下使用 scp 命令Linux
- 《Linux下sed命令的使用》Linux
- linux下svn命令的使用Linux
- 【備忘】解決錯誤:undefined reference to `cv::imread(cv::String const&, int)‘Undefined
- linux壓縮和解壓縮命令整理Linux
- linux檔案壓縮和解壓命令Linux
- linux壓縮和解壓命令總結Linux
- linux壓縮和解壓縮命令大全Linux
- 如果你訪問一個網站很慢,怎麼排查和解決?網站
- g++連結報錯:undefined reference to typeinfo of xxxUndefined
- linux下svn命令使用大全(share)Linux
- Linux tar壓縮和解壓縮等命令Linux
- zblog報錯:Undefined index: ZC SIDEBAR6 ORDER的原因和解決辦法UndefinedIndexIDE
- zblogphp提示“ Call to undefined function openssl_pkey_get_public()”的原因和解決辦法PHPUndefinedFunction
- A20核心編譯錯誤undefined reference to `hwmon_device_register編譯Undefineddev
- Ubuntu下Linux配置核心各種常見錯誤和解決辦法UbuntuLinux
- 在 Linux 命令列下使用“原力”Linux命令列
- Linux 下使用 killall 命令終止程式Linux
- linux下ping命令使用詳解Linux
- Linux下ulimit、find命令使用者LinuxMIT
- "undefined reference to strptime"之自己定義strptime函式Undefined函式
- Linux系統下find、locate命令如何使用?Linux
- Linux下SSH命令使用方法詳解Linux