2016-12-14 65 views
5

試圖編譯這個cfgparser example鏈接器無法找到符號,但它們在那裏?

$ g++ example.cc -lcfgparser 
: In function `main': 
example.cc:(.text+0x6b): undefined reference to `ConfigParser_t::readFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' 
example.cc:(.text+0x160): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0x2d9): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int*) const' 
example.cc:(.text+0x43c): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, double*) const' 
example.cc:(.text+0x5b1): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool*) const' 
example.cc:(.text+0x78c): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*) const' 
example.cc:(.text+0xa15): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0xba2): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0xd15): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
example.cc:(.text+0xe7f): undefined reference to `ConfigParser_t::getValue(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*) const' 
collect2: error: ld returned 1 exit statu 

但顯然這些符號有:

$ nm -gC /usr/lib/libcfgparser.so 
000000000003710 T ConfigParser_t::readFile(std::string const&) 
0000000000004880 T ConfigParser_t::ConfigParser_t(std::string const&) 
00000000000024c0 T ConfigParser_t::ConfigParser_t() 
0000000000004ad0 T ConfigParser_t::ConfigParser_t(std::string const&) 
00000000000024a0 T ConfigParser_t::ConfigParser_t() 
0000000000004d20 T ConfigParser_t::getOptions(std::string const&) const 
00000000000028d0 T ConfigParser_t::getSections() const 
0000000000002ff0 T ConfigParser_t::getValue(std::string, std::string, bool*) const 
0000000000002de0 T ConfigParser_t::getValue(std::string, std::string, double*) const 
0000000000002bd0 T ConfigParser_t::getValue(std::string, std::string, int*) const 
00000000000027d0 T ConfigParser_t::getValue(std::string, std::string, std::string*) const 
0000000000003500 T ConfigParser_t::getValue(std::string, std::string, std::vector<std::string, std::allocator<std::string> >*) const 

不像上的其他類似的問題,這是不是鏈接順序,因爲只有一個目標文件被鏈接。我錯過了什麼?

+1

我的猜測是,這兩個模塊的構建方式使得'std :: string'對他們意味着不同的東西。可能與不同風格的C++運行時庫鏈接? –

+0

如果您複製了示例代碼,則問題可能是您包含'stdio.h'而不是'cstdio'。這將匹配與char相關的東西斷開的鏈接。其他的事情要檢查:你的'libcfgparser.so'是用'std :: string'構建的,它支持'wchar_t'? – starturtle

+0

我有同樣的問題確保ABI兼容性,確保-m32/-m64與您的庫/可執行文件版本匹配。 – ceorron

回答

11

但顯然這些符號有:

顯然,他們不是。仔細看一下,你會發現 由你的 鏈接器報告的特徵與未報告的特徵之間沒有任何匹配,從 nm報告的特徵之間沒有匹配。

標準頭<string>std::string定義爲的typedef:

std::basic_string<char, std::char_traits<char>, std::allocator<char>> 

的GCC實現的<string>,作爲cxx11 ABI(GCC 4.7.0) std::string定義爲一個typedef的:

std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> 

std::__cxx11名稱空間包含的二進制實現符合cxx1的 類型1 ABI。

這類型定義是指C++翻譯單元,其包括標準頭<string>不會 編譯,用GCC> = 4.7,到含有該demangles作爲std::string一個符號的目標代碼。

如果二元 - 就像你libcfgparser.so - 包含一個符號,demangles爲std::string,然後 無論該符號可能在從它被建造的消息人士稱,它並不是指std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, 而不能與其他編譯了std::string定義的二進制文件相鏈接。

libcfgparser.so是一個從 cfgparser Sourceforce project (這是最後更新三年前)由libcfgparser0_1.1.2_amd64.deb安裝。我想這是因爲我 得到您的鏈接錯誤,與鏈接相同的example.cc程序與該程序包安裝的庫鏈接。 - 前期cxx11 ABI

/usr/lib$ strings -a libcfgparser.so | grep "GCC: (" 
GCC: (Debian 4.3.2-1.1) 4.3.2 
... 

它告訴我們這個圖書館建與GCC 4.3.2:

了錯誤的解釋被發現。

出現在您nm輸出的std::string是預先cxx11 demangling的std::basic_string<char, std::char_traits<char>, std::allocator<char>>縮寫 。

這個libcfgparser.so是與您當前的GCC ABI不兼容的,所以您的 不能將它與您使用該編譯器構建的程序鏈接。你可以做的是 建立libcfgparser從源代碼包,libcfgparser-1.1.2.tar.bz2, 與您當前的編譯器,然後鏈接您的程序與你自己建立的庫 。

這有效,但不是毫不費力。首先,您需要修復損壞的 和源代碼包的過時自動工具,以創建一個工作的./configure 腳本。

這並沒有給出包裝維護者熟練程度的令人放心的印象。 加上該軟件包的源代碼,版權2008,是業餘質量。如果 你以後是用於INI風格文件的C++解析器,那麼boost::property_tree::ini_parser將是 轉到解決方案。請參閱this answer

+0

謝謝!你的回答非常有幫助和教育。我在猜測類似的原因,但我不能總結可能是因爲「'nm'輸出中出現的'std :: string'是'std :: basic_string ,std :: allocator >'''''''''''''''''''''''''''''''''''''''''''''我不知道怎麼正確地去縮寫'std :: string'。 – qweruiop

+0

同樣使用'boost :: property_tree :: ini_parser'是一個很好的調用 – qweruiop

+0

@qweruiop不客氣,'std :: string'(demangled)='Ss'(mangled)是pre-cxx11 GCC名稱中的一個* hardcoded *縮寫,它不是邏輯,而是方便。可以指望的是,二進制文件中的符號(無論是破壞的還是去結構的),* *不同*與鏈接器* *不同,'因爲它們是鏈接器所看到的。 –

相關問題