Description of problem: I have an application that I develop that has 3 levels of inlines. If I compile with -O2 the app crashes, with -O1 the app doesn't crash. The app also works with gcc 4.0, gcc 3.4.5, gcc 3.2.2, etc. Version-Release number of selected component (if applicable): [sdake@clever ~]$ gcc --version gcc (GCC) 4.1.0 20060304 (Red Hat 4.1.0-3) Copyright (C) 2006 Free Software Foundation, Inc. T How reproducible: 100% Steps to Reproduce: 1. untar attached openais-trunk.tar.gz and cd into openais-trunk directory 2. run make in top level directory 3. cd lcr 4. type ./test Actual results: program segfaults. It appears data is corrupted around the lcr_comp_find function which inlines several other functions. If I specify a "noinline" attribute to the functoin the code works. See attachment. Expected results: [root@shih lcr]# ./test UIS server thread started 4 A - version 0 constructor context 0xaaaa0000 B - version 0 constructor context 0xbbbb0000 A - version 1 constructor context 0xaaaa1111 B - version 1 constructor context 0xbbbb1111 A - version 0 func1 A - version 0 func2 A - version 0 func3 A - version 1 func1 A - version 1 func2 A - version 1 func3 B - version 0 func1 B - version 0 func2 B - version 0 func3 B - version 1 func1 B - version 1 func2 B - version 1 func3 Additional info: attached trunk version of openais attached patch which works around apparent optimizer bug in gcc
Created attachment 127684 [details] trunk tarball of openais source code
Created attachment 127685 [details] patch to workaround the problem in the optimizer patch that works around the problem also putting printfs in the lcr_comp_find functions seems to fix it
The source is buggy, violates strict aliasing (and additionally by additional cast clearly just makes a GCC warning go away rather than fixing a bug in it). See info gcc, search for -fstrict-aliasing or better yet the ISO C99 standard. After fixing it the program no longer segfaults: --- lcr/lcr_ifact.c.jj 2006-03-24 09:28:12.000000000 +0100 +++ lcr/lcr_ifact.c 2006-04-13 11:51:00.000000000 +0200 @@ -88,7 +88,10 @@ static inline struct lcr_component_insta unsigned int version, int *iface_number) { - struct lcr_component_instance *instance; + union { + struct lcr_component_instance *instance; + void *ptr; + } u; unsigned int component_handle = 0; int i; @@ -97,14 +100,14 @@ static inline struct lcr_component_insta */ hdb_iterator_reset (&lcr_component_instance_database); while (hdb_iterator_next (&lcr_component_instance_database, - (void **)(void *)&instance, &component_handle) == 0) { + &u.ptr, &component_handle) == 0) { - for (i = 0; i < instance->iface_count; i++) { - if ((strcmp (instance->ifaces[i].name, iface_name) == 0) && - instance->ifaces[i].version == version) { + for (i = 0; i < u.instance->iface_count; i++) { + if ((strcmp (u.instance->ifaces[i].name, iface_name) == 0) && + u.instance->ifaces[i].version == version) { *iface_number = i; - return (instance); + return (u.instance); } } hdb_handle_put (&lcr_component_instance_database, component_handle); @@ -116,7 +119,10 @@ static inline struct lcr_component_insta static inline int lcr_lib_loaded ( char *library_name) { - struct lcr_component_instance *instance; + union { + struct lcr_component_instance *instance; + void *ptr; + } u; unsigned int component_handle = 0; /* @@ -124,9 +130,9 @@ static inline int lcr_lib_loaded ( */ hdb_iterator_reset (&lcr_component_instance_database); while (hdb_iterator_next (&lcr_component_instance_database, - (void **)(void *)&instance, &component_handle) == 0) { + &u.ptr, &component_handle) == 0) { - if (strcmp (instance->library_name, library_name) == 0) { + if (strcmp (u.instance->library_name, library_name) == 0) { return (1); }
Thanks Jakub for the info about strict aliasing and the bugfix. Unfortunately I think we use this type of thing alot so there will be many more code changes. Thanks again for the pointer. Regards -steve