-3

I am having a problem with some C code built with gcc compiler. The code in question has an enum, whose values are used as cases in a switch statement to configure an object. Fairly standard stuff.

When I compile the code using the -O0 option flag, everything builds and runs correctly no problem. However, when the flag is set to -O2 the code no longer works as expected.

When I step through the code and put a watch on the local variables, the enum, which should be only be one of three enum values, is actually -104! This causes the program to fail to configure the object.

Has anyone encountered this before who could provide some guidance? I haven't encountered this before and would appreciate if someone could explain why the compiler does this so I can make any necessary changes.

Snippet of code in question:

value = 0u;

switch(test_config) { 
    case DISABLE:
        break;

    case INTERNAL:
        value = 1u;
        break;

    case EXTERNAL:
        value = 2u;
        break;

    default:
        valid = FALSE;
        break;
} 

if (valid) { 
    configure_test(value);
} 

Enum in question:

typedef enum  {
    DISABLE,
    INTERNAL, 
    EXTERNAL
} test_config_t;

This is the code that is causing the problem. I initially didn't include it because I didn't want the question to be please fix my code, rather I have been googling looking for reasons why gcc optimisation flags would produce different results for the same piece of code and haven't found anything particularly helpful. Also I am not at my computer and had to type this on my phone which also doesn't help. So I came here because there are experts here who know way more than me that could point me in the right direction.

Some more info that I probably should have included. The code runs on hardware which also might be the problem and I am looking into that as well. When ran from FSBL the code works with -O0, but not with -O2. So it may be hardware, but then I don't know why it works one way not the other.

mrwolf
  • 41
  • 1
  • 12

1 Answers1

2

You don't give enough details (since your question don't show any actual code, it should have some MCVE) but you very probably have some undefined behavior and you should be scared.

Remember that C11 or C99 (like most programming languages) is defined by an explicit specification (not only by the concrete behaviour observed on your code) written in English and partly defining the runtime behaviour of a valid C program. Read n1570.

I strongly recommend reading Lattner's blog What Every C programmer should know about Undefined Behavior before even touching or compiling your source code.

I recommend at least compiling with (nearly) all warnings and debug info, e.g. with gcc -Wall -Wextra -g, then improve the code to get no warnings, and run it under the gdb debugger and valgrind. Read more about Invoking GCC. You may also use (temporarily) some sanitizer instrumentation options, notably -fsanitize=undefined and -fsanitize=address. You could also add -std=gnu99 and -pedantic to your compiler flags. Notice that gdb watchpoints are a very useful debugger feature to find why a value has changed or is unexpected.

When you compile for release or for benchmarking with optimizations enabled, keep also the warning flags (so compile with gcc -O2 -Wall -Wextra); optimizations might give extra warnings which you should also correct. BTW, GCC accepts both -O2 and -g at the same time.

When you observe such issues, question first your own code before suspecting the compiler
(because compilers are very well tested; I found only one compiler bug in almost 40 years of programming).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    You also want `-pedantic` and some `-std` option such as `-std=gnu99`. – melpomene Jul 25 '17 at 08:06
  • One could want to use GNU extensions, which `-pedantic` forbids. – Basile Starynkevitch Jul 25 '17 at 08:09
  • `-pedantic` doesn't forbid GNU extensions. – melpomene Jul 25 '17 at 08:09
  • @melpomene: this is not what the [warning options of GCC](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html) documentation says – Basile Starynkevitch Jul 25 '17 at 08:10
  • Yeah, sloppy wording on my part. It depends on what is meant by "forbid" (`-pedantic` doesn't error out, it just emits warnings) and "GNU extensions" (e.g. https://gcc.gnu.org/onlinedocs/gcc/Alternate-Keywords.html#Alternate-Keywords says "*`-pedantic` and other options cause warnings for many GNU C extensions*", i.e. it doesn't warn for all of them, just many). – melpomene Jul 25 '17 at 08:15
  • Thanks. I will try sanitize to see if I can figure this out. I am already using all the other options you provided, except using `-std=c99` instead. – mrwolf Jul 25 '17 at 09:38
  • And you certainly need to use the debugger. watchpoints should be really helpful. – Basile Starynkevitch Jul 25 '17 at 11:07