3

I have a question regarding weak attribute of const variable. I have the following couple of files compiled with 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);
}

other.c:

const int my_var = 200;

When I compile these two files and run the application I get the following result:

my_var = 100

Since I'm using weak attribute on the my_var variable in main.c I thought it should be overridden by my_var variable in other.c, but that wasn't the case...

Now if I drop the const keyword of my_var in 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);
}

Then re-compile, I get the desired result:

my_var = 200

Which is what I expect.

Note: If I drop the const in the file other.c I still get the result of 200.

My question is: why using const keyword changes the behaviour of weak attribute? Is it related to which section the variable resides in?

The Makefile I'm using is:

.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)

Thanks in advance,

user6083108
  • 31
  • 1
  • 3
  • AFAIK weak attribute is for functions. – LPs Mar 18 '16 at 15:15
  • 1
    @LPs: It is for both. Only the description is in the functions attribute, the var-attributes just refer tothat. – too honest for this site Mar 18 '16 at 15:21
  • 1
    you may need to compile with -fno-common for this to work. – fuz Mar 18 '16 at 15:22
  • @Olaf Thx. What about their usage? E.g. for a library, is that supposed to pre-define and init a global variable that the library require to be defined by library user? It looks horrible to me... – LPs Mar 18 '16 at 15:26
  • @LPs: I currently use them for functions only, but the approach should be the same. I think in general, using `weakref` plus an alias is the better approach for both usages. But making them a global symbol (i.e. external linkage) should be the first stage. – too honest for this site Mar 18 '16 at 15:39
  • @FUZxxl `-fno-common` didn't work for me. @Olaf The usage in my case is as follows: We have internal API which takes as input, a configuration struct. The customer wants to be able to change this internal configuration, so as minimal effort, we want this configuration struct to be weak, then, the customer would be able to override it with his own customized configuration. My only problem is with `const` where it is like 'cancelling' the weak attribute – user6083108 Mar 18 '16 at 19:04

2 Answers2

1

I faced the same issue (cf. GCC optimization bug on weak const variable) and came up with the conclusion that gcc does not handle well the optimization on the weak/const variable within the file where the weak definition is: in your 'main.c' file, my_var is always resolved to 100.
Not sure, but it seems to be a gcc bug (?).

To solve this, you can :

  • prevent optimization, by adding the -O0 option to gcc.
    • -O0 should be the default value, so this might not help...
  • get rid of the const keyword as you did: gcc cannot optimize no more as my_var can potentially change now.
  • set your const int my_var __attribute__((weak)) = 100; statement in a separate source file ('main_weak.c' for instance): while building 'main.c', gcc does not know the my_var value and thus won't optimize.
Lrnt Gr
  • 369
  • 2
  • 9
0

The identifiers have internal linkage. This is an obsolecense feature (static storage class specifier should be used). In general, you should have a header with an extern declaration of the identifier:

extern const int my_var;

Linking with different qualifiers is a bad idea.

Maybe the better understandable approach is to use wekref plus alias.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • You're right about the header file, I didn't add it to the example I wrote here, however, it doesn't change the phenomena: using `const` is like cancelling weak attribute. My question is: why when I drop the `const` qualifier it works as expected? Another question: When you said that this is an obsolecense feature, did you refer to weak variables? Thanks – user6083108 Mar 18 '16 at 19:24
  • @user6083108: The C standard does not even mention `__attribute__`, even less `weak` whatsoever. Note that the `weak` attribute of gcc actually refers to the **symbol** generated for the variable (that is a linker/assembler-term, not a C). A C variable has additional properties like type. The `weak` attribute actually adds a lower-than-C language property to the symbol. No offence, but may I recommend to do some more research on this (quite complicated) subject? Maybe you are really better off using `weakref`. To me, this is more clear than how `weak` works in a global context. – too honest for this site Mar 18 '16 at 19:48
  • For the obsolescence: I did not mention `weak` in this context. – too honest for this site Mar 18 '16 at 19:49
  • 1
    Dear @Olaf, no offence taken. I know C standard doesn't mention attributes nor weak symbols, and that each toolchain (gcc/arm/etc...) has its own attributes and linker options. I'm doing a research and part of it is posting here, hopefully to get an answer, but I still didn't get one. My question is pretty simple (not saying the answer is): How does `const` affect `weak` attribute on GCC? That's my question! – user6083108 Mar 18 '16 at 20:33
  • It should not. But having two different declarations for and the same object in C is typically undefined behaviour. So anything can happen. Hopefully you will get a better answer; I'd have to research myself, as I only used `weakref` (IIRC, I tried to use `weak`, but had trouble, too and `weakref` solved the problem). – too honest for this site Mar 18 '16 at 20:37