2016-10-05 6 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の確認は、そのシンボルをエクスポートし、ライブラリ自体はGCCに-vを使用することによって発見された:

... 
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で微妙に変化しました。

clangまたはgccのどちらを使用しても同じ結果が得られます。

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

+0

[missing -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(視認性が隠されて)問題を引き起こしています。私は空白の定義に置き換えて、それはすべてOKです。はい、私はまたclangのための同等物を持っていました、それは同じ方法で失敗した理由です。

これは、Cコードではこれらのシンボルが隠されていることしか見ていないため、実際に存在していたにもかかわらずそれらをインポートできなかったことです。

0

あなたは(私が説明からわかるように、既に行わ)extern "C"としてMEM_priv_alloc()機能をマークしたりextern "C" { /* function implementation */ }に関数本体をラップする必要があります。 もMEM_priv_allocプロトタイプがどのように行われるか再確認してくださいヘッダー

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

EXTERNC int MEM_priv_alloc (void); 

__cplusplusextern "C"を組み合わせて使用​​します。

ファイル:

たとえば、 MEM_priv_allocinline(残念ながら、私はこれのphisicsを知らない、しかし 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

ええ、もっと複雑なことが間違っていると思われます。このコード(および私がまだ手に入れていない他のライブラリ)は、すでにWindows用のmsvc2015で完全にビルドされており、メモリデバッグを無効にすると機能します(MEM_priv *関数は決して使用またはエクスポートされません)。私はそれを最小限にとどめて、今晩遅く見つけたものを見てみましょう。 – ZXcvbnM

関連する問題