3

I compiled the following code with gcc 4.8.4 and with -O0 flag:

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

static jmp_buf env;

static void
doJump(int nvar, int rvar, int vvar)
{
    printf("Inside doJump(): nvar=%d rvar=%d vvar=%d\n", nvar, rvar, vvar);
    longjmp(env, 1);
}

int
main(int argc, char *argv[])
{
    int nvar;
    register int rvar;          
    volatile int vvar;         

    nvar = 111;
    rvar = 222;
    vvar = 333;

    if (setjmp(env) == 0) {     
        nvar = 777;
        rvar = 888;
        vvar = 999;
        doJump(nvar, rvar, vvar);
    } else {                    
        printf("After longjmp(): nvar=%d rvar=%d vvar=%d\n", nvar, rvar, vvar);
    }

    exit(EXIT_SUCCESS);
}

It produced the following output:

Inside doJump(): nvar=777 rvar=888 vvar=999
After longjmp(): nvar=777 rvar=222 vvar=999

My expectation was that rvar will be 888 in the second row as all optimizations are disabled.

When I remove 'register' from definition of 'rvar' or when I add 'volatile' in front of 'register', it outputs 888.

So it seems that gcc still performs some optimizations inspite of -O0 flag.

Is there a way to disable absolutely all optimizations in gcc?

Hrant
  • 496
  • 1
  • 5
  • 13
  • What's your definition of an "optimization"? (I am not being funny; this is a serious question.) – NPE Aug 09 '15 at 17:28
  • In the particular case it puts 'rvar' in a register. Isn't that an optimization? – Hrant Aug 09 '15 at 17:31
  • 4
    It's hard to call the compiler putting something in register an optimization when you told it to put it in a register. – Ross Ridge Aug 09 '15 at 17:31
  • According to [this answer](http://stackoverflow.com/a/1393474/1287251), `setjmp` works by saving the registers to the stack (and then `longjmp` just restores those registers from the stack). If that's the case, then it makes sense, as `rvar` would be saved at `setjmp` and its later modifications would not. In this case, I don't think you're observing any optimizations here at all. – Cornstalks Aug 09 '15 at 17:36
  • register keyword just "advises" the compiler to put it in a register. – Hrant Aug 09 '15 at 17:37
  • Hrant, what optimizations are you thinking are taking place? I don't think the compiler is doing any optimizations. – Cornstalks Aug 09 '15 at 17:39

2 Answers2

6

The C11 standard says for longjmp():

All accessible objects have values, and all other components of the abstract machine249) have state, as of the time the longjmp function was called, except that the values of objects of automatic storage duration that are local to the function containing the invocation of the corresponding setjmp macro that do not have volatile-qualified type and have been changed between the setjmp invocation and longjmp call are indeterminate.

249) This includes, but is not limited to, the floating-point status flags and the state of open files.

You are running into indeterminate values...standard conforming behaviour.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
3

if your posted code is compiled with all warnings enabled, as it should have been, then three warnings are output:

warning: unused parameter 'argc' [-Wunused-parameter]

warning: unused parameter 'argv' [-Wunused-parameter]

the above can be fixed with replacing:

int main( int argc, char *argv[])

with

int main( void )

and the important one:

warning: variable 'ravr' might be clobbered by 'longjmp' or 'vfork' [-Wclobbered]

Which answers you question and shows that compiling has to be done with all warnings enabled. for gcc, at a minimum use:

-Wall -Wextra -pedantic
user3629249
  • 16,402
  • 1
  • 16
  • 17