简体   繁体   English

为什么gcc使用-O0进行一些优化

[英]Why gcc does some optimizations with -O0

I compiled the following code with gcc 4.8.4 and with -O0 flag: 我使用gcc 4.8.4和-O0标志编译了以下代码:

#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. 我的期望是rvar在第二行将是888,因为所有优化都被禁用。

When I remove 'register' from definition of 'rvar' or when I add 'volatile' in front of 'register', it outputs 888. 当我从'rvar'的定义中删除'register'或者在'register'前面添加'volatile'时,它输出888。

So it seems that gcc still performs some optimizations inspite of -O0 flag. 因此,尽管-O0标志,​​gcc似乎仍然会执行一些优化。

Is there a way to disable absolutely all optimizations in gcc? 有没有办法在gcc中禁用所有优化?

The C11 standard says for longjmp() : 对于longjmp() ,C11标准说:

All accessible objects have values, and all other components of the abstract machine 249) 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的所有其他组件在调用longjmp函数时具有状态,除了包含调用的函数的本地的自动存储持续时间的对象的值。没有volatile限定类型并且在setjmp调用和longjmp调用之间已经更改的相应setjmp宏是不确定的。

249) This includes, but is not limited to, the floating-point status flags and the state of open files. 249)这包括但不限于浮点状态标志和打开文件的状态。

You are running into indeterminate values...standard conforming behaviour. 你正在遇到不确定的价值......标准的符合行为。

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: 对于gcc,至少使用:

-Wall -Wextra -pedantic

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM