SimonHF's Blog

Just another WordPress.com site

a gcc bug: optimization (-O) of code using union unexpectedly causes essential code to be optimized away February 12, 2011

Filed under: Uncategorized — simonhf @ 6:49 pm

Having written hundreds of thousands of lines of C during my career, I’ve never found a bug in gcc unless I’ve been trying to do something well off the beaten track. So it came as a surprise to discover this nasty bug in gcc 4.5.1 and I share it here. Note: The code below works perfectly with Microsoft compilers and gcc 3.x compilers.

Reproduce with:


mingw32-gcc.exe -DWITH_UNNECESSARY_CODE    example.c -oexample.exe && example.exe
mingw32-gcc.exe                            example.c -oexample.exe && example.exe
mingw32-gcc.exe -DWITH_UNNECESSARY_CODE -O example.c -oexample.exe && example.exe
mingw32-gcc.exe                         -O example.c -oexample.exe && example.exe

Shows output:


C:\20110211-gcc-bug>mingw32-gcc.exe -DWITH_UNNECESSARY_CODE    example.c -oexample.exe   && example.exe
before  copy_bytes(): source     : abcd
before  copy_bytes(): destination: 1234
calling copy_bytes(): copy source to destination
after   copy_bytes(): source     : abcd
after   copy_bytes(): destination: abcd <-- expected

C:\20110211-gcc-bug>mingw32-gcc.exe                            example.c -oexample.exe   && example.exe
before  copy_bytes(): source     : abcd
before  copy_bytes(): destination: 1234
calling copy_bytes(): copy source to destination
after   copy_bytes(): source     : abcd
after   copy_bytes(): destination: abcd <-- expected

C:\20110211-gcc-bug>mingw32-gcc.exe -DWITH_UNNECESSARY_CODE -O example.c -oexample.exe   && example.exe
before  copy_bytes(): source     : abcd
before  copy_bytes(): destination: 1234
calling copy_bytes(): copy source to destination
after   copy_bytes(): source     : abcd
after   copy_bytes(): destination: abcd <-- expected

C:\20110211-gcc-bug>mingw32-gcc.exe                         -O example.c -oexample.exe   && example.exe
before  copy_bytes(): source     : abcd
before  copy_bytes(): destination: 1234
calling copy_bytes(): copy source to destination
after   copy_bytes(): source     : abcd
after   copy_bytes(): destination: 1234 <-- not expected: the bug in action

example.c:


#include <stdio.h>
#include <stdlib.h>

typedef union PTR_UNION
{
    char * as_s08_ptr;
    unsigned int as_u32;
} PTR_UNION;

void copy_bytes(unsigned int address_as_u32, char * source, unsigned int size)
{
    unsigned int i;
    PTR_UNION destination;

    destination.as_u32 = address_as_u32;

    for (i=0 ; i<size; i++) {
        destination.as_s08_ptr[i] = source[i];
    }

#ifdef WITH_UNNECESSARY_CODE
    if ((size >= 1) && (destination.as_s08_ptr[0] != source[0])) {
        exit(1);
    }
#endif
}

void main(void)
{
    PTR_UNION address;
    char source[] = "abcd";
    char destination[] = "1234";

    printf("before  copy_bytes(): source     : %s\n", source);
    printf("before  copy_bytes(): destination: %s\n", destination);

    printf("calling copy_bytes(): copy source to destination\n");
    address.as_s08_ptr = destination;
    copy_bytes(address.as_u32, source, sizeof(source));

    printf("after   copy_bytes(): source     : %s\n", source);
    printf("after   copy_bytes(): destination: %s <-- %s\n", destination,
        strcmp(source, destination) ? "not expected: the bug in action" : "expected");
}

The bug is filed here.

Advertisements
 

One Response to “a gcc bug: optimization (-O) of code using union unexpectedly causes essential code to be optimized away”

  1. jason Says:

    It amazes me that after all these years I can still follow all of this code. My Uni Prof would be proud 😛 I realize you were stuck in the U.S. for 4 weeks, but… more posts! I’m adding the RSS to Mac Mail 🙂

    Thanks for making our conversations a highlight of my trip, Simon!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s