首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GCC -O2与__attribute__((弱))

GCC -O2与__attribute__((弱))
EN

Stack Overflow用户
提问于 2017-04-03 05:41:02
回答 2查看 3.1K关注 0票数 5

看起来GCC和-O2__attribute__((weak))会根据你引用弱符号的方式产生不同的结果。考虑到这一点:

$ cat弱.c

代码语言:javascript
复制
#include <stdio.h>

extern const int weaksym1;
const int weaksym1 __attribute__(( weak )) = 0;

extern const int weaksym2;
const int weaksym2 __attribute__(( weak )) = 0;

extern int weaksym3;
int weaksym3 __attribute__(( weak )) = 0;

void testweak(void)
{
    if ( weaksym1 == 0 )
    {
        printf( "0\n" );
    }
    else
    {
        printf( "1\n" );
    }

    printf( "%d\n", weaksym2 );


    if ( weaksym3 == 0 )
    {
        printf( "0\n" );
    }
    else
    {
        printf( "1\n" );
    }
}

$ cat测试。c

代码语言:javascript
复制
extern const int weaksym1;
const int weaksym1 = 1;

extern const int weaksym2;
const int weaksym2 = 1;

extern int weaksym3;
int weaksym3 = 1;

extern void testweak(void);

void main(void)
{
    testweak();
}

$ make

代码语言:javascript
复制
gcc  -c weak.c
gcc  -c test.c
gcc  -o test test.o weak.o

$./测试

代码语言:javascript
复制
1
1
1

$ make ADD_FLAGS="-O2“

代码语言:javascript
复制
gcc -O2 -c weak.c
gcc -O2 -c test.c
gcc -O2 -o test test.o weak.o

$./测试

代码语言:javascript
复制
0
1
1

问题是,为什么最后的"./test“产生”01 1“而不是”11 1"?

gcc 5.4.0版(GCC)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-03 07:11:59

看起来,在进行优化时,编译器在声明为const的符号和在同一个编译单元中的weak定义方面存在问题。

您可以创建一个单独的c文件并将const弱定义移到那里,它可以解决这个问题:

weak_def.c

代码语言:javascript
复制
const int weaksym1 __attribute__(( weak )) = 0;
const int weaksym2 __attribute__(( weak )) = 0;

问题中描述的相同问题:常量变量上的GCC弱属性

票数 3
EN

Stack Overflow用户

发布于 2017-04-03 08:07:01

摘要:

只有当不将弱符号初始化为值时,弱符号才能正确工作。链接器负责初始化(如果不存在相同名称的普通符号,则始终将它们初始化为零)。

如果您尝试将弱符号初始化为任何值,甚至像OP一样将其初始化为零,则C编译器可以对其值进行奇怪的假设。编译器没有区分弱符号和普通符号;它是所有(动态)链接器魔术。

若要修复,请从声明为“弱”的任何符号中删除初始化(= 0):

代码语言:javascript
复制
extern const int weaksym1;
const int weaksym1 __attribute__((__weak__));

extern const int weaksym2;
const int weaksym2 __attribute__((__weak__));

extern int weaksym3;
int weaksym3 __attribute__((__weak__));

详细说明:

C语言没有"弱符号“的概念。它是使用ELF文件格式的ELF文件格式和(动态)链接器提供的功能。

正如man 1 nm手册页在"V"部分描述的那样,

当弱定义符号与法线定义符号链接时,正常定义符号被使用时没有错误。当弱未定义符号被链接且符号未定义时,弱符号的值变为零,没有错误。

弱符号声明不应初始化为任何值,因为如果进程没有与同名的普通符号链接,则该声明的值为零。( man 1 nm页面中的“已定义”指ELF符号表中存在的符号。)

“弱符号”特性的设计是为了与现有的C编译器一起工作。记住,C编译器对“弱”和“正常”符号没有任何区别。

为了确保这在不违反C编译器行为的情况下工作,必须未初始化“弱”符号,以便C编译器不能对其值作出任何假设。相反,它将生成像往常一样获取符号地址的代码--这就是正常/弱符号查找魔术发生的地方。

这也意味着弱符号只能被“自动初始化”为零,而不能被任何其他值,除非被相同名称的普通初始化符号“重写”。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43177223

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档