pqy@localhost ~/src/test/a $ cat m.c
#include <stdio.h>
int aaaaa __attribute__ ((weak)) =8;
int main(void){
printf("%dn", aaaaa);
return 0;
}
pqy@localhost ~/src/test/a $ cat lib.c
int aaaaa = 5;
pqy@localhost ~/src/test/a $ gcc lib.c -fPIC -shared -o libb.so;gcc m.c -o m -L. -lb -Wl,-rpath=$PWD;./m
8
以上是我的代码和测试结果。我很困惑为什么它没有按预期工作。
还要尝试功能,而不是工作乙醚。以下是测试结果。
pqy@localhost ~/src/test/a $ cat lib.c
int fun() {
return 5;
}
pqy@localhost ~/src/test/a $ cat m.c
#include <stdio.h>
__attribute__((weak)) int fun() {
return 8;
}
int main(void){
printf("%dn", fun());
return 0;
}
pqy@localhost ~/src/test/a $ gcc lib.c -fPIC -shared -o libb.so;gcc m.c -O0 -o m -L. -lb -Wl,-rpath=$PWD;./m
8
pqy@localhost ~/src/test/a $ ldd m
linux-vdso.so.1 (0x00007ffd819ec000)
libb.so => /home/pqy/src/test/a/libb.so (0x00007f7226738000)
libc.so.6 => /lib64/libc.so.6 (0x00007f7226533000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7226744000)
pqy@localhost ~/src/test/a $
在底部,您在这里观察到的只是链接器不会 如果符号可以静态解析,则动态解析符号。看:
主.c
extern void foo(void);
extern void need_dynamic_foo(void);
extern void need_static_foo(void);
int main(void){
foo();
need_dynamic_foo();
need_static_foo();
return 0;
}
dynamic_foo.c
#include <stdio.h>
void foo(void)
{
puts("foo (dynamic)");
}
void need_dynamic_foo(void)
{
puts(__func__);
}
static_foo.c
#include <stdio.h>
void foo(void)
{
puts("foo (static)");
}
void need_static_foo(void)
{
puts(__func__);
}
编译源代码,以便:
$ gcc -Wall -c main.c static_foo.c
$ gcc -Wall -fPIC -c dynamic_foo.c
创建共享库:
$ gcc -shared -o libfoo.so dynamic_foo.o
并链接程序:
$ gcc -o prog main.o static_foo.o libfoo.so -Wl,-rpath=$PWD
它的运行方式如下:
$ ./prog
foo (static)
need_dynamic_foo
need_static_foo
因此,foo
和need_static_foo
被静态解析为来自static_foo.o
和libfoo.so
foo
的定义被忽略了,尽管事实上libfoo.so
是需要的,并提供了need_dynamic_foo
的定义。这没什么区别 如果我们将链接顺序更改为:
$ gcc -o prog main.o libfoo.so static_foo.o -Wl,-rpath=$PWD
$ ./prog
foo (static)
need_dynamic_foo
need_static_foo
如果我们将static_foo.c
替换为,也没有任何区别:
static_weak_foo.c
#include <stdio.h>
void __attribute__((weak)) foo(void)
{
puts("foo (static weak)");
}
void need_static_foo(void)
{
puts(__func__);
}
编译并重新链接:
$ gcc -Wall -c static_weak_foo.c
$ gcc -o prog main.o libfoo.so static_weak_foo.o -Wl,-rpath=$PWD
$ ./prog
foo (static weak)
need_dynamic_foo
need_static_foo
尽管static_weak_foo.c
中对foo
的定义现在被宣布为薄弱,foo
可以静态解析到这个定义的事实 仍然抢占了动态解决它的任何需求。
现在,如果我们编写另一个源文件,其中包含另一个强定义foo
:
static_strong_foo.c
#include <stdio.h>
void foo(void)
{
puts("foo (static strong)");
}
并编译它并链接如下:
$ gcc -Wall -c static_strong_foo.c
$ gcc -o prog main.o static_weak_foo.o libfoo.so static_strong_foo.o -Wl,-rpath=$PWD
我们看到:
$ ./prog
foo (static strong)
need_dynamic_foo
need_static_foo
现在,libfoo.so
仍然提供了need_dynamic_foo
的定义,因为那里 不是别的;static_weak_foo.o
仍然提供了need_static_foo
的唯一定义, 并且libfoo.so
中foo
的定义仍然被忽略,因为符号 可以静态解析。
但在这种情况下,不同文件中foo
有两种定义,它们是 可用于静态解决它:static_weak_foo.o
和static_strong_foo.o
中的强定义.根据您的链接规则 熟悉,强定义胜出。
如果这两个静态链接的foo
定义都很强,那么当然会有一个 多重定义错误,就像:
$ gcc -o prog main.o static_foo.o libfoo.so static_strong_foo.o -Wl,-rpath=$PWD
static_strong_foo.o: In function `foo':
static_strong_foo.c:(.text+0x0): multiple definition of `foo'
static_foo.o:static_foo.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
其中libfoo.so
中的动态定义没有发挥作用。所以你可以 以以下实用原则为指导: 您熟悉的仲裁规则 在联动中同一符号的弱定义和强定义之间仅适用于 竞争定义,这将在没有定义的情况下引发多重定义错误 的weak
属性。
符号在链接阶段解析,在链接阶段,只有弱符号aaaaa = 8
可见。
如果符号可以在链接阶段解析,它不会生成重新定位条目,那么在加载阶段不会发生任何事情
重新定位表中没有aaaaa
:
% objdump -R m
m: file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0000000000003dc8 R_X86_64_RELATIVE *ABS*+0x0000000000001130
0000000000003dd0 R_X86_64_RELATIVE *ABS*+0x00000000000010f0
0000000000004028 R_X86_64_RELATIVE *ABS*+0x0000000000004028
0000000000003fd8 R_X86_64_GLOB_DAT _ITM_deregisterTMCloneTable
0000000000003fe0 R_X86_64_GLOB_DAT __libc_start_main@GLIBC_2.2.5
0000000000003fe8 R_X86_64_GLOB_DAT __gmon_start__
0000000000003ff0 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable
0000000000003ff8 R_X86_64_GLOB_DAT __cxa_finalize@GLIBC_2.2.5
0000000000004018 R_X86_64_JUMP_SLOT printf@GLIBC_2.2.5
Сompiler 或链接器以相反的顺序从命令行构建文件。换句话说,带有(弱))的文件应该比动态文件更早地位于命令行中。