2016-10-05 69 views
3

現在已經連續打了48個小時,嘗試將動態庫鏈接到其依賴項時,仍然收到未定義的引用錯誤 - 儘管所有導出都存在,並且庫已成功找到。ld未定義的參考,儘管已找到庫並已導出符號

場景:

  • libmemory(C++) - 出口與extern "C"
  • libstring(C)函數 - 出口的功能,從libmemory

libmemory進口成功生成:

$ g++ -shared -fPIC -o ./builds/libmemory.so ...$(OBJECTS)... 

libstring編譯成功,但未能鏈接:

$ gcc -shared -fPIC -o ./builds/libstring.so ...$(OBJECTS)... -L./builds -lmemory 
./temp/libstring/string.o: In function `STR_duplicate': 
string.c:(.text+0x1cb): undefined reference to `MEM_priv_alloc' 
./temp/libstring/string.o: In function `STR_duplicate_replace': 
string.c:(.text+0x2a0): undefined reference to `MEM_priv_free' 
string.c:(.text+0x2bf): undefined reference to `MEM_priv_alloc' 
/usr/bin/ld: ./builds/libstring.so: hidden symbol `MEM_priv_free' isn't defined 
/usr/bin/ld: final link failed: Bad value 
collect2: error: ld returned 1 exit status 

驗證libmemory出口的符號和庫本身是通過使用-v到GCC發現:

... 
attempt to open ./builds/libmemory.so succeeded 
-lmemory (./builds/libmemory.so) 
... 

$ nm -gC ./builds/libmemory.so | grep MEM_ 
0000000000009178 T MEM_exit 
0000000000009343 T MEM_init 
00000000000093e9 T MEM_print_leaks 
00000000000095be T MEM_priv_alloc 
000000000000971d T MEM_priv_free 
00000000000099c1 T MEM_priv_realloc 
0000000000009d26 T MEM_set_callback_leak 
0000000000009d3f T MEM_set_callback_noleak 

$ objdump -T ./builds/libmemory.so | grep MEM_ 
0000000000009d3f g DF .text 0000000000000019 Base  MEM_set_callback_noleak 
00000000000093e9 g DF .text 00000000000001d5 Base  MEM_print_leaks 
0000000000009d26 g DF .text 0000000000000019 Base  MEM_set_callback_leak 
00000000000099c1 g DF .text 0000000000000365 Base  MEM_priv_realloc 
0000000000009343 g DF .text 00000000000000a6 Base  MEM_init 
00000000000095be g DF .text 000000000000015f Base  MEM_priv_alloc 
000000000000971d g DF .text 00000000000002a4 Base  MEM_priv_free 
0000000000009178 g DF .text 00000000000000a7 Base  MEM_exit 

$ readelf -Ws ./builds/libmemory.so | grep MEM_ 
    49: 0000000000009d3f 25 FUNC GLOBAL DEFAULT 11 MEM_set_callback_noleak 
    95: 00000000000093e9 469 FUNC GLOBAL DEFAULT 11 MEM_print_leaks 
    99: 0000000000009d26 25 FUNC GLOBAL DEFAULT 11 MEM_set_callback_leak 
    118: 00000000000099c1 869 FUNC GLOBAL DEFAULT 11 MEM_priv_realloc 
    126: 0000000000009343 166 FUNC GLOBAL DEFAULT 11 MEM_init 
    145: 00000000000095be 351 FUNC GLOBAL DEFAULT 11 MEM_priv_alloc 
    192: 000000000000971d 676 FUNC GLOBAL DEFAULT 11 MEM_priv_free 
    272: 0000000000009178 167 FUNC GLOBAL DEFAULT 11 MEM_exit 
    103: 0000000000009343 166 FUNC GLOBAL DEFAULT 11 MEM_init 
    108: 0000000000009178 167 FUNC GLOBAL DEFAULT 11 MEM_exit 
    148: 0000000000009d3f 25 FUNC GLOBAL DEFAULT 11 MEM_set_callback_noleak 
    202: 00000000000095be 351 FUNC GLOBAL DEFAULT 11 MEM_priv_alloc 
    267: 000000000000971d 676 FUNC GLOBAL DEFAULT 11 MEM_priv_free 
    342: 0000000000009d26 25 FUNC GLOBAL DEFAULT 11 MEM_set_callback_leak 
    346: 00000000000099c1 869 FUNC GLOBAL DEFAULT 11 MEM_priv_realloc 
    366: 00000000000093e9 469 FUNC GLOBAL DEFAULT 11 MEM_print_leaks 

有什麼可怕的簡單的我失蹤?所有其他相關的問題都有簡單的答案,例如鏈接庫的順序和使用的路徑 - 但我已經驗證它們已經到位並按預期工作。

-fvisibility修修補補導致沒有任何變化。

相同的結果是否存在使用鐺或GCC。

Linux 3.16.0-38-generic gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)

+0

[缺少'-soname'](http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html)與您的問題有什麼關係? –

+0

@AdrianColomitchi嘗試在兩者中添加一個合適的-soname參數,沒有區別 – ZXcvbnM

+0

@Leon,-DC的輸出與-gC的輸出很相似 – ZXcvbnM

回答

0

所以,我剝出合併的最後部分的詳細信息,以及發現的問題。

我的導入/導出爲藍本關閉的這一點:https://gcc.gnu.org/wiki/Visibility

我相當於實施最終看起來像這樣:

#  if GCC_IS_V4_OR_LATER 
#    define DLLEXPORT  __attribute__((visibility("default"))) 
#    define DLLIMPORT  __attribute__((visibility("hidden"))) 
#  else 
#    define DLLEXPORT 
#    define DLLIMPORT 
#  endif 

的dllimport的(可見性隱藏)引起的問題;我用一個空白的定義替換它,它都可以。是的,我也有類似的鏗鏘聲,這也是爲什麼它也以相同的方式失敗的原因。

我從這裏得到的結論是,C代碼只將這些可能的符號看作是隱藏的,因此無論嘗試多麼困難,無論它們實際存在多少,都不能導入它們!

0

你應該標記MEM_priv_alloc()功能extern "C"或包裹函數體爲extern "C" { /* function implementation */ }(已經做了,我可以從描述看)。在頭部的__cplusplusextern "C" 並運用組合

#ifdef __cplusplus 
    #define EXTERNC extern "C" 
#else 
    #define EXTERNC 
#endif 

EXTERNC int MEM_priv_alloc (void); 

也請仔細檢查MEM_priv_alloc原型是如何完成的。例如,MEM_priv_alloc應該inline(不幸的是我不知道這個物理學中,但是inline例如失敗對我來說)


下面是簡化的例子,對我的作品:

文件:

$ ls 
main.c Makefile mem.cpp mem.h strings.c strings.h 

mem.cpp

#include <stdio.h> 
#include "mem.h" 
extern "C" int MEM_priv_alloc (void) 
{ 
    return 0; 
} 

mem.h

#ifdef __cplusplus 
    #define EXTERNC extern "C" 
#else 
    #define EXTERNC 
#endif 
EXTERNC int MEM_priv_alloc (void); 

strings.c:

#include <stdio.h> 
#include "mem.h" 
int STR_duplicate_replace (void) 
{ 
    MEM_priv_alloc(); 
} 

字符串。H:

int STR_duplicate_replace (void); 

的main.c

#include <stdio.h> 
#include "string.h" 
int main (void) 
{ 
    STR_duplicate_replace(); 
    return 0; 
} 

的Makefile:

prog: libmemory.so libstrings.so 
     gcc -o [email protected] -L. -lmemory -lstrings main.c 

libmemory.so: mem.cpp 
     g++ -shared -fPIC -o [email protected] $^ 

libstrings.so: strings.c 
     gcc -shared -fPIC -o [email protected] $^ 

,並生成日誌:

g++ -shared -fPIC -o libmemory.so mem.cpp 
gcc -shared -fPIC -o libstrings.so strings.c 
gcc -o prog -L. -lmemory -lstrings main.c 

請一個LSO看到 Using C++ library in C codewiki How to mix C and C++

+0

是的,我懷疑更復雜的事情是錯誤的。這個代碼(以及其他我尚未得到的庫)已經在msvc2015 for Windows中完全構建,並且如果我禁用了我的內存調試(因此MEM_priv *函數從未被使用或導出),它也可以工作。我會把它分解成最小的,看看我今晚晚些時候會發現什麼。 – ZXcvbnM

相關問題