ld未定义的参考,尽管已找到库并已导出符号
现在已经连续打了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)
所以,我剥出合并的最后部分的详细信息,以及发现的问题。
我的导入/导出为蓝本关闭的这一点: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代码只将这些可能的符号看作是隐藏的,因此无论尝试多么困难,无论它们实际存在多少,都不能导入它们!
你应该标记MEM_priv_alloc()
功能extern "C"
或包裹函数体为extern "C" { /* function implementation */ }
(已经做了,我可以从描述看)。在头部的__cplusplus
和extern "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 code和 wiki How to mix C and C++
是的,我怀疑更复杂的事情是错误的。这个代码(以及其他我尚未得到的库)已经在msvc2015 for Windows中完全构建,并且如果我禁用了我的内存调试(因此MEM_priv *函数从未被使用或导出),它也可以工作。我会把它分解成最小的,看看我今晚晚些时候会发现什么。 – ZXcvbnM
[缺少'-soname'](http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html)与您的问题有什么关系? –
@AdrianColomitchi尝试在两者中添加一个合适的-soname参数,没有区别 – ZXcvbnM
@Leon,-DC的输出与-gC的输出很相似 – ZXcvbnM