It looks like GCC with -O2
and __attribute__((weak))
produces different results depending on how you reference your weak symbols. Consider this:
$ cat weak.c
#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 test.c
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
gcc -c weak.c
gcc -c test.c
gcc -o test test.o weak.o
$ ./test
1
1
1
$ make ADD_FLAGS="-O2"
gcc -O2 -c weak.c
gcc -O2 -c test.c
gcc -O2 -o test test.o weak.o
$ ./test
0
1
1
The question is, why the last "./test" produces "0 1 1", not "1 1 1"?
gcc version 5.4.0 (GCC)
"V"
. If you remove the zero initializations, you'll see that your code will perform predictably regardless of optimizations or type/method of reference. – Timon