目前我在Mac OS X 10.6.7和Xcode 4.0.2上遇到了一个弱链接的问题。
$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
根据开发者文档,我们可以使用gcc attribute((weak_import))来进行弱连接符号。
然而,以下示例代码总是会抛出编译错误,如下所示:
weak.c:
#include <stdlib.h>
#include <stdio.h>
extern int SayHello() __attribute__((weak));
int main()
{
int result;
if (SayHello!=NULL)
{
printf("SayHello is present!\n");
result=SayHello();
}
else
printf("SayHello is not present!\n");
}
错误信息如下:
$ gcc weak.c
Undefined symbols for architecture x86_64:
"_f", referenced from:
_main in cceOf2wN.o
(maybe you meant: __dyld_func_lookup)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
即使使用选项 -undefined dynamic_lookup
,在运行时仍会抛出错误:
$ gcc -undefined dynamic_lookup weak.c
$ ./a.out
dyld: Symbol not found: _SayHello
Referenced from: /private/tmp/o/./a.out
Expected in: dynamic lookup
Trace/BPT trap
nm -m
命令对于 "a.out" 文件的输出如下:
$ nm -m a.out | grep Hello
(undefined) external _SayHello (dynamically looked up)
如下所预期的:
(undefined) weak external _SayHello (dynamically looked up)
然而,在Ubuntu上使用gcc编译(Ubuntu/Linaro 4.4.4-14ubuntu5)4.4.5时,它按预期工作:
weak.c:
#include <stdlib.h>
#include <stdio.h>
extern int SayHello() __attribute__((weak));
int main()
{
int result;
if (SayHello!=NULL)
{
printf("SayHello is present!\n");
result=SayHello();
}
else
printf("SayHello is not present!\n");
}
$ gcc weak.c
$ ./a.out
SayHello is not present!
SayHello 的二进制符号为:
$ nm a.out | grep Hello
w SayHello
"w" 符号是一个未被标记为弱对象符号的弱符号。
我测试了旧版的Xcode 3.2,结果符合预期。
有谁可以帮我解决这个问题吗?这是ld的一个bug吗?
我发现更有趣的事情。当我创建一个虚拟库来导出动态库中的SayHello符号时,它的效果就如预期。
dummy.c:
int SayHello() {
return;
}
$ gcc -dynamiclib -o libdummy.dylib dummy.c
$ gcc weak.c libdummy.dylib
$ ./a.out
SayHello is present!
如果"libdummy.dylib"不存在:
$ rm libdummy.dylib
$ ./a.out
SayHello is not present!
正常工作!弱符号现在在nm消息中,如预期所示:
$ nm -m a.out | grep Hello
(undefined) weak external _SayHello (from libdummy)
__attribute__((weak))
而不是__attribute__((weak_import))
?我正在寻找类似问题的解决方法。 - C0deH4cker