http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50466

             Bug #: 50466
           Summary: Compiled code behaves differently with "-O2 -fPIC"
                    flag combination
    Classification: Unclassified
           Product: gcc
           Version: 4.3.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: hmil...@gluster.com


Compiled code behaves differently with "-O2 -fPIC" flag combination. Taking out
either of the flags makes the compiled code behave predictably.

Also, commenting out certain lines in the code (highlighted as comments) makes
the code compile predictably even in the presence of "-O2 -fPIC".

Other compiler versions always behave predictably for this test case.

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


struct list_head {
        struct list_head *next;
        struct list_head *prev;
};


struct pool {
        struct list_head list;
        int count;
        unsigned long size;
        void *slab;
};


char global_init;


/* Uncommenting the prototype with attribute masks the bug */ //void *__calloc
(size_t nmemb, size_t size) __attribute_malloc__;

void *
__calloc (size_t nmemb, size_t size)
{
        return calloc (nmemb, size);
}


void
pool_validate (struct pool *pool)
{
        struct list_head *list = NULL;
        struct list_head *head = NULL;
        int count = 0;

        head = &pool->list;

        for (list = head->next; list != head; list = list->next) {
                count++;
        }

        if (pool->count == count) {
                printf ("GOOD :)\n");
        } else {
                printf ("BAD :(\n");
        }
}


struct pool *
pool_new (int size, int count)
{
        struct pool *pool = NULL;
        void *slab = NULL;
        int i = 0;
        struct list_head *list = NULL;
        struct list_head *head = NULL;


        /* commenting the below line hides the bug */
        do { if (!global_init) break; } while (0);

        pool = __calloc (sizeof (*pool), 1);
        if (!pool)
                return NULL;

        head = &pool->list;
        head->next = head->prev = head;

        pool->size = size;
        pool->count = count;

        slab = __calloc (count, size);
        if (!slab) {
                free (pool);
                return NULL;
        }

        for (i = 0; i < count; i++) {
                list = slab + (i * (size));

                list->next = list->prev = list;

                list->next = head;
                list->prev = head->prev;
                list->next->prev = list;
                list->prev->next = list;
        }
        pool->slab = slab;
        return pool;
}


int main (int argc, char *argv[])
{
        struct pool *pool = NULL;
        pool = pool_new (1024, 1024);
        pool_validate (pool);
        return 0;
}

-------------
blackhole:~/comp-bug # gcc --version
gcc (SUSE Linux) 4.3.4 [gcc-4_3-branch revision 152973] Copyright (C) 2008 Free
Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

blackhole:~/comp-bug # make all
gcc-4.3 -Wall -O0 -fPIC pool.c -o good
gcc-4.3 -Wall -O2 -fPIC pool.c -o bad
./good
GOOD :)
./bad
BAD :(

Reply via email to