【问题标题】:GCC weak attribute on constant variables常量变量的 GCC 弱属性
【发布时间】:2016-03-18 15:07:29
【问题描述】:

我有一个关于 const 变量的弱属性的问题。我有以下几个用 gcc 编译的文件:

main.c:

#include <stdio.h>

const int my_var __attribute__((weak)) = 100;

int
main(int argc, char *argv[])
{
  printf("my_var = %d\n", my_var);
}

其他.c:

const int my_var = 200;

当我编译这两个文件并运行应用程序时,我得到以下结果:

my_var = 100

由于我在 main.c 中的 my_var 变量上使用了弱属性,我认为它应该被 other.c 中的 my_var 变量覆盖,但事实并非如此......

现在如果我将my_varconst 关键字放到main.c 中:

#include <stdio.h>
/* Dropping const... */
int my_var __attribute__((weak)) = 100;

int
main(int argc, char *argv[])
{
  printf("my_var = %d\n", my_var);
}

然后重新编译,我得到了想要的结果:

my_var = 200

这是我所期望的。

注意:如果我将 const 放到文件 other.c 中,我仍然会得到 200 的结果。

我的问题是:为什么使用const 关键字会改变weak 属性的行为?是否与变量所在的部分有关?

我使用的 Makefile 是:

.PHONY: all clean

TARGET=test
OBJS=main.o other.o

all: $(TARGET)

$(TARGET): $(OBJS)
    gcc $(OBJS) -o $(TARGET)

main.o:main.c
    gcc -c main.c

other.o:other.c
    gcc -c other.c

clean:
    rm -rf *.o $(TARGET)

提前致谢,

【问题讨论】:

  • AFAIK 弱属性适用于函数。
  • @LPs:两者都适用。只有描述在functions属性中,var-attributes只是引用那个。
  • 您可能需要使用 -fno-common 进行编译才能使其正常工作。
  • @Olaf 谢谢。他们的用法呢?例如。对于库,是否应该预先定义和初始化库需要由库用户定义的全局变量?这对我来说看起来很可怕......
  • @LPs:我目前仅将它们用于功能,但方法应该相同。我认为一般来说,使用weakref 加上别名是两种用法的更好方法。但是让它们成为全局符号(即外部链接)应该是第一阶段。

标签: c gcc attributes


【解决方案1】:

我遇到了同样的问题(参见GCC optimization bug on weak const variable)并得出结论,gcc 无法很好地处理文件中弱定义为:weak/const 变量的优化:在您的“main.c”文件中,my_var 始终解析为 100
不确定,但这似乎是一个gcc 错误(?)。

要解决这个问题,您可以:

  • 通过将-O0 选项添加到gcc 来防止优化。
    • -O0 应该是默认值,所以这可能无济于事...
  • 像您一样删除 const 关键字:gcc 无法再优化,因为 my_var 现在可能会发生变化。
  • 在单独的源文件中设置const int my_var __attribute__((weak)) = 100; 语句(例如'main_weak.c'):在构建'main.c' 时,gcc 不知道my_var 的值,因此不会优化。

【讨论】:

  • 您也可以将-O1替换为各个优化选项。
【解决方案2】:

标识符具有内部链接。这是一个过时的特性(应该使用static 存储类说明符)。一般来说,你应该有一个带有 extern 标识符声明的标题:

extern const int my_var;

用不同的限定词链接是个坏主意。

也许更好理解的方法是使用wekref 加上alias

【讨论】:

  • 你说的头文件是对的,我没有将它添加到我在这里写的示例中,但是它并没有改变现象:使用const就像取消弱属性一样。我的问题是:为什么当我删除 const 限定符时它会按预期工作?另一个问题:当你说这是一个过时的特性时,你是指弱变量吗?谢谢
  • @user6083108:C 标准甚至没有提到__attribute__,更不用说weak。请注意,gcc 的weak 属性实际上是指为变量生成的符号(即链接器/汇编器术语,而不是C)。 C 变量具有其他属性,例如类型。 weak 属性实际上为符号添加了低于 C 语言的属性。没有冒犯,但我可以建议对这个(相当复杂的)主题做更多的研究吗?也许你最好使用weakref。对我来说,这比 weak 在全球范围内的工作方式更清楚。
  • 对于过时:我没有在这种情况下提到weak
  • 亲爱的@Olaf,没有冒犯。我知道 C 标准没有提到属性或弱符号,并且每个工具链(gcc/arm/etc...)都有自己的属性和链接器选项。我正在做一项研究,其中一部分发布在这里,希望能得到答案,但我仍然没有得到答案。我的问题很简单(不是说答案是):const 如何影响 GCC 上的weak 属性?这是我的问题!
  • 不应该。但是在 C 中对同一个对象有两个不同的声明通常是未定义的行为。所以任何事情都可能发生。希望你能得到更好的答案;我必须自己研究,因为我只使用了weakref(IIRC,我尝试使用weak,但也遇到了问题,weakref 解决了这个问题)。
猜你喜欢
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
相关资源
最近更新 更多