Curious global variable bug? Bad assumptions on my part?
Tony Wetmore
tony.wetmore@solipsys.com
Thu Feb 14 16:17:00 GMT 2008
Tynan,
I think the difference is that when GCC optimizes the code, it
eliminates the g_counter variable entirely, since it "never changes"
within the body of the loop, so the loop becomes "while(false) ;".
When you add the "volatile" qualifier, you are instructing GCC not to
optimize the variable away, since its value may change in ways that are
unpredictable by GCC.
If you look at the assembly code generated in the -O0 and -O1 cases, the
difference should be very obvious in this simple test case.
--
Tony Wetmore
Tynan Wilke wrote:
> Hello list,
>
> If I am posting in the wrong place, I apologize. I was making some
> test scripts this morning and found a pretty glaring difference
> between my optimized (-O1) versus my unoptimized (-O0) test code.
> Below, is the a quick example that I made showing the problem:
> --------------------------------
> #include <pthread.h>
> #include <stdio.h>
> #include <stdlib.h>
>
> static int g_counter = 0;
>
> void *IncThread(void* nothing)
> {
> printf("Thread started\n");
> while( 1 )
> {
> g_counter++;
> // printf("thread g_counter: %d\n", g_counter );
> }
> return NULL;
> }
>
> int main()
> {
> pthread_t thread;
> if ( 0 != pthread_create(&thread, NULL, IncThread, NULL ) )
> {
> perror("Failed to create thread");
> exit(1);
> }
>
> printf("Waiting for counter...\n");
> while ( g_counter == 0 );
>
> while ( g_counter < 1000000 )
> printf("g_counter: %d\n", g_counter);
>
> printf("Done!\n");
> return 0;
> }
> --------------------------------
>
> And compile as follows:
> $ gcc -O0 -lpthread main.c -o out
>
> When run, gives the expected output:
> $ ./out
> Waiting for counter...
> Thread started
> g_counter: 734
> g_counter: 9198
> g_counter: 10334
> g_counter: 11109
> ... snip ...
> g_counter: 986568
> g_counter: 987310
> Done!
>
> If I compile with -O1, the issue arrises:
> $ gcc -O1 -lpthread main.c -o out
> $ ./out
> Waiting for counter...
> Thread started
>
> And nothing else is printed out since it is stuck on the first while
> loop because g_counter is remains 0 in the main thread (but it is
> getting incremented in IncThread). I get the same results if g_counter
> is not static. The code works fine if I make g_counter volatile.
>
> Here is the gcc version I'm using, which is straight from the RH repo:
> $ gcc -v
> Using built-in specs.
> Target: i386-redhat-linux
> Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
> --infodir=/usr/share/info --enable-shared --enable-threads=posix
> --enable-checking=release --with-system-zlib --enable-__cxa_atexit
> --disable-libunwind-exceptions --enable-libgcj-multifile
> --enable-languages=c,c++,objc,obj-c++,java,fortran,ada
> --enable-java-awt=gtk --disable-dssi --enable-plugin
> --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
> --with-cpu=generic --host=i386-redhat-linux
> Thread model: posix
> gcc version 4.1.2 20070626 (Red Hat 4.1.2-14)
>
> Also, I'm on a quad-core Xeon, if that makes a difference.
>
> I have to imagine that this is due to some bad assumptions on my end,
> but I would really like to know why optimising this relatively
> straightforward code causes it to behave differently. Any help is
> greatly appreciated.
>
> Thanks,
> Tynan
>
>
More information about the Gcc-help
mailing list