Article View: comp.unix.programmer
Article #3659Re: gcc -O2 bug
From: Thomas Wolf
Date: Thu, 08 Aug 1996 00:00
Date: Thu, 08 Aug 1996 00:00
136 lines
6073 bytes
6073 bytes
In article <4ubnat$75u@freeside.fc.net>, mrbig@freeside.fc.net (Mike Big) writes:
:> /*
:> I'v found what I think might be a bug in gcc's optimization. The
:> code below works corectly when compiled using "gcc -Wall -O1"
:> but fails when compiled using "gcc -Wall -O2". I'v tried it using
:> both gcc 2.7.2 & 2.6.3 on Linux 1.3.100, Linux 2.0.10, & SunOS 4.1.3
:> w/ the same result. The problem is that eventhough flag gets set to
:> 0, the while loop does NOT exit. Also, when you uncomment the printf
:> inside the loop, all is well again even w/ the -O2 optimizations.
:> Any ideas are welcome. (This is my first time using signals, so
:> maybe something is wrong there but I still think the -O2 should not
:> change things.)
:>
:> Thanx in advance,
:> Mike
:> */
:>
:> #include <stdio.h>
:> #include <sys/time.h>
:> #include <sys/types.h>
:> #include <signal.h>
:>
:> void fca(); /* SIGALRM handler function */
:>
:> long counter;
:> int *flag_pt;
:>
:> int main()
:> {
:> struct itimerval timer_length;
:> int flag;
:>
:> flag_pt=&flag;
:> /* specify signal handler */
:> signal(SIGALRM, fca);
:>
:> /* set the signal to repeat every 3 seconds */
:> timer_length.it_value.tv_sec=3; /* initial time */
:> timer_length.it_value.tv_usec=0;
:> timer_length.it_interval.tv_sec=3; /* repeat */
:> timer_length.it_interval.tv_usec=0;
:> setitimer(ITIMER_REAL, &timer_length, NULL);
:>
:> flag=time(NULL); /* this is so that the compiler won't substitute a constant
:> for flag as it might if I did something like flag=1; */
:>
:> /* count until interrupted (after 3 seconds) */
:> counter=0;
:> while(flag){ /* does NOT exit when using gcc -O2 */
:> counter++;
:> /* uncomenting the printf below will fix things. weird heh */
:> /* printf("counter=%ld flag=%d\n",counter,flag); */
:> }
:>
:> exit(0);
:> }
:>
:> void fca()
:> {
:> printf("counter=%ld\n",counter);
:> printf("before flag=%d\n",*flag_pt);
:> *flag_pt=0;
:> printf("after flag=%d\n",*flag_pt);
:> }
The error you describe is not due to the compiler: it's in your
program. There are several problems with your code (ignoring all
the system dependencies with timers etc.).
1. Take a look at the prototype of 'signal'. It's equivalent to the
following:
typedef void (*Signal_Handler) (int);
Signal_Handler signal (int sig, Signal_Handler func);
(I took apart the definition given in the standard in order to
clarify things.)
As you can see, a signal handler must be a function that takes one
'int' argument and returns 'void'. Your 'fca' function should there-
fore be declared as
void fca (int sig);
2. A signal handler is only allowed to do a few things. The standard
says:
[ISO/IEC 9899:1990(E), 7.7.1.1]
"... the behavior is undefined if the signal handler calls any
function in the standard library other than the 'signal' function
itself (with a first argument of the signal corresponding to the
signal that caused the invocation of the handler) or refers to any
object with static storage duration other than by assigning a value
to a static duration variable of type 'volatile sig_atomic_t'".
In particular, this means that you may not call 'printf' in your
signal handler.
It also tells you that static data that you access from within a
signal handler must have type 'volatile sig_atomic_t'. Your 'flag_pt'
has type 'int *', and so your signal handler is not allowed to access
it.
3. Your problem occurred because you didn't tell the compiler that
'flag' can be modified in ways unbeknownst to the compiler. If you
had declared 'flag' as 'volatile int', the program might have worked
despite points (1) and (2). The 'volatile' qualifier basically tells
the copmpiler that it must not optimize away accesses to a variable.
But note: even if it works when you add 'volatile', the program still
invokes undefined behavior due to points (1) and (2), and you should
correct it.
4. Your problem disappeared when you uncommented the 'printf' in the
loop because the compiler could not be sure that 'printf' didn't
modify 'flag' through an access through 'flag_pt', and thus it
couldn't optimize away the test on 'flag' in the loop condition.
5. How your compiler determined that 'time' does not return something
that results in 'flag' == 0 is a mystery to me. Maybe it didn't and
this is just its version of undefined behavior?
6. '-O2' may well change things since it tells the compiler to use more
optimizations than with '-O1'. With '-O1', it apparently didn't try
to optimize the loop, with '-O2', it did.
Best regards,
Thomas
----------------------------------------------------------------------
Swiss Federal Institute of Technology | Thomas Wolf
Software Engineering Laboratory | EPFL-DI-LGL
Thomas Wolf (TW) | CH-1015 Lausanne (Suisse)
E-Mail: wolf@di.epfl.ch | Phone: (++41 21)693 42 37
----------------------------------------------------------------------
Technical Details
Message-ID:
<3209b0dc.0@epflnews.epfl.ch>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailReferences:
<4ubnat$75u@freeside.fc.net>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 11318c,7d30cae02ba9b089 X-Google-Attributes: gid11318c,public X-Google-Thread: 10c696,7d30cae02ba9b089 X-Google-Attributes: gid10c696,public X-Google-Thread: 1014db,7d30cae02ba9b089 X-Google-Attributes: gid1014db,public X-Google-Thread: fc89c,7d30cae02ba9b089 X-Google-Attributes: gidfc89c,public From: Thomas.Wolf@di.epfl.ch (Thomas Wolf) Subject: Re: gcc -O2 bug Date: 1996/08/08 Message-ID: <3209b0dc.0@epflnews.epfl.ch> X-Deja-AN: 172889569 sender: wolf@lglsun6.epfl.ch (Thomas Wolf) references: <4ubnat$75u@freeside.fc.net> organization: Ecole Polytechnique F�d�rale de Lausanne keywords: gcc bug O2 newsgroups: comp.unix.programmer,gnu.gcc.help,comp.os.linux.development.apps,comp.lang.c