gpt4 book ai didi

linux - __attribute__ ((weak)) 不适用于全局变量

转载 作者:太空狗 更新时间:2023-10-29 11:17:01 24 4
gpt4 key购买 nike

pqy@localhost ~/src/test/a $ cat m.c
#include <stdio.h>
int aaaaa __attribute__ ((weak)) =8;
int main(void){
printf("%d\n", 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("%d\n", 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 $

最佳答案

在底部,您在这里观察到的只是链接器不会如果符号可以静态解析,则动态解析符号。见:

ma​​in.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

因此 fooneed_static_foo 被静态解析为 static_foo.o 中的定义,并且来自 libfoo.sofoo 的定义被忽略,尽管 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.cfoo 的定义现在被声明为弱的,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 中的动态定义 没有任何作用。所以你可以遵循这一实用原则:您熟悉的仲裁规则链接中相同符号的弱定义和强定义之间仅适用与竞争对手的定义 在缺席的情况下会引起多重定义错误 属性

关于linux - __attribute__ ((weak)) 不适用于全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54452223/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com