- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
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 $
最佳答案
在底部,您在这里观察到的只是链接器不会如果符号可以静态解析,则动态解析符号。见:
main.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
中的动态定义 没有任何作用。所以你可以遵循这一实用原则:您熟悉的仲裁规则链接中相同符号的弱定义和强定义之间仅适用与竞争对手的定义 在缺席的情况下会引起多重定义错误 弱
属性。
关于linux - __attribute__ ((weak)) 不适用于全局变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54452223/
我有一个目前正在用 C 编写的应用程序,其中我在作为项目一部分的库中声明了几个 TLS 静态全局变量。 TLS 变量是使用 gcc 的 __thread 指令声明的。 我想知道我是否可以使用 .cto
如果 C++ 类构造函数只能通过其参数访问数据,那么它们是否可以并且应该声明为 __attribute__((pure))?在什么情况下它们应该被限定为 __attribute__((const))?
遵循 GCC __attribute__(packed) 将打包到字节边界,对齐用于此目的:-- u8 rx_buf[14] __attribute__((aligned(8))); struct
__attribute__((const)) 和 GNU C 中的 __attribute__((pure)) 有什么区别? __attribute__((const)) int f() {
这个问题不太可能对任何 future 的访客有帮助;它只与一个较小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于全世界的互联网受众。如需帮助使此问题更广泛适用,visit the
我想利用 GCC 的可见性属性。 为此,在我的可执行文件中,我有一个函数,我希望它对任何插件都可见,这样它们就可以使用它来注册自己。因此,我在其上使用 __attribute__((visibilit
有时我会出于各种原因围绕 printf 风格的函数编写包装器,我真的很喜欢让 clang 告诉我格式说明符和实际参数之间的类型不匹配。考虑: #include #include static __
我对以下代码行有疑问: char buffer[256] __attribute__((aligned(4096))); 全局数组“缓冲区”的内容是字符串,我从标准输入中获取。我读过https://g
在gcc documentation它们提供有关整数如何对齐的信息。 打包整数可以做同样的事情吗? 例如,这在不会自动处理不正确对齐数据的系统上有效吗? typedef uint16_t __attr
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: GCC __attribute__((aligned(x)) explanation What is mea
__attribute__ 指令是否适用于一行中声明的所有成员? int a, b, c; 声明三个 int 变量。 int *a, b, c; 将变量“a”声明为指向 int 的指针,将 b 和 c
在使用 gcc __attribute__ 函数时,我注意到代码生成存在差异,具体取决于我放置属性的位置。在下面的示例中,我希望编译器不要优化我对 use() 的调用。 编译器:x86-64 gcc(
为什么gcc需要__attribute__((__malloc__))?难道不应该通过将 malloc (和类似的函数)声明为返回 restricted 指针来传达相同的信息 (void *restr
我得到了一段将 __attribute__((const)) 应用于某些函数的代码。现在,我宁愿在它可用时不删除它,但另一方面,我确实想要更便携,所以 - 我想说 #if some condition
我可能对 weak 理解有误: 我的情况: 具有一些弱回调的“物理层” 实现这些回调的“框架层”,并为应用层提供新的 WEAK 回调 主要 - 应用层。 phy.h #pragma once void
我知道从C编程语言的角度main() 是程序的入口点。 但从操作系统的角度来看,__start 位于 ctrt0 启动例程,它链接到一个程序中,该程序在调用程序的 main() 函数(如有错误请指正)
这几天一直让我抓狂。如果我将数组声明为 static,则无法让数组对齐 16。 非常感谢任何帮助。 修订版: #include #include #define MAX_INPUTS 250 in
我正在尝试在 android NDK 上进行开发。我实际上有一个带有模块的项目+子文件夹(编译为静态库)并与主项目文件(libs .a + main object .o --> 可执行文件)链接在一起
这个问题在这里已经有了答案: Is there a standard "never returns" attribute for C# functions? (10 个答案) 关闭 8 年前。 C#
__attribute__ ((__packed__)) 对嵌套结构有什么影响?例如: // C version struct __attribute__ ((__packed__)) { s
我是一名优秀的程序员,十分优秀!