gcc -O2优化到错误的行为,这是一个错误吗?

Iva*_*van 1 c optimization gcc

我编写了一个非常简单的程序来测试gcc -O2选项,它会产生错误的行为.这是gcc的bug吗?

我的C程序:

#include <stdio.h>

int main(int argc, char **argv)
{
    unsigned long i = 0;
    while (1) {
        if (++i > 0x1fffffffUL) {
            printf("hello\n");
            i = 0;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我用-O1编译它时,一切都是正确的,我在每个循环中加1.但是当我用-O2编译它时,我被忽略,在每个循环中输出"hello".为什么-O2会导致这种错误行为?是gcc的明显错误吗?我的gcc版本对于cygwin是4.8.3,我尝试了一个新版本,它也有同样的问题.

用-O1编译,汇编代码是:

Disassembly of section .text:

    00000000 <_main>:
    #include <stdio.h>

    int main(int argc, char **argv)
    {
       0:   55                      push   %ebp
       1:   89 e5                   mov    %esp,%ebp
       3:   83 e4 f0                and    $0xfffffff0,%esp
       6:   83 ec 10                sub    $0x10,%esp
       9:   e8 00 00 00 00          call   e <_main+0xe>
       e:   b8 00 00 00 20          mov    $0x20000000,%eax
        unsigned long i = 0;
        while (1) {
            if (++i > 0x1fffffffUL) {
      13:   83 e8 01                sub    $0x1,%eax
      16:   75 fb                   jne    13 <_main+0x13>
                printf("hello\n");
      18:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
      1f:   e8 00 00 00 00          call   24 <_main+0x24>
      24:   eb e8                   jmp    e <_main+0xe>
      26:   90                      nop
      27:   90                      nop
Run Code Online (Sandbox Code Playgroud)

用-O2编译,汇编代码是:

Disassembly of section .text.startup:

00000000 <_main>:
#include <stdio.h>

int main(int argc, char **argv)
{
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 10                sub    $0x10,%esp
   9:   e8 00 00 00 00          call   e <_main+0xe>
   e:   66 90                   xchg   %ax,%ax
  10:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
  17:   e8 00 00 00 00          call   1c <_main+0x1c>
  1c:   eb f2                   jmp    10 <_main+0x10>
  1e:   90                      nop
  1f:   90                      nop
Run Code Online (Sandbox Code Playgroud)

dus*_*uff 6

这种优化是正确的.

-O1,编译器基本上将您的函数重写为:

for (;;) {
    for (int i = 0; i < 0x20000000; i++) {
    }
    printf("hello\n");
}
Run Code Online (Sandbox Code Playgroud)

-O2,正在优化空循环.


Art*_*Art 5

对我来说听起来不是一个小虫.为什么编译器生成的代码会在程序的可观察行为在无限循环中输出"hello \n"时浪费时间.您不需要增加无用的变量.