是gcc的选项-O2打破这个小程序还是我具有不确定的行为 [英] Is GCC's option -O2 breaking this small program or do I have undefined behavior

查看:244
本文介绍了是gcc的选项-O2打破这个小程序还是我具有不确定的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了一个非常大的应用程序这个问题,从它做了SSCCE。我不知道code是否未定义的行为或 -O2 打破它。

在与编译它的gcc -o变交流A.EXE -O2 -Wall -Wextra -Werror 它打印的 5

但它打印的 25 不编译时 -O2 (如 -O1 )或取消注释2注释行之一(prevent内联)。

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
// __attribute __((noinline始终))
INT F(INT *待办事项,INT输入){
    为int * CUR =待办事项-1; //修复++在循环的开始
    INT结果=输入;
    而(1){
        CUR ++;
        INT CH = * CUR;
        //的printf((%I)\\ n,CH);
        开关(CH){
            案件0:;
                转到结束;
            情况1:;
                结果=结果*结果;
            打破;
        }
    }
    结束:
    返回结果;
}
诠释主(){
    INT待办事项[] = {1,0}; // 1:方形,0:结束
    INT输入= 5;
    INT结果= F(待办事项,输入);
    的printf(=%I \\ N,结果);
    的printf(结束\\ n);
    返回0;
}

是gcc的选项 -O2 打破这个小程序或者我有什么地方未定义的行为?


解决方案

 为int * CUR =待办事项-1;

调用未定义的行为。 待办事项 - 1 是一个无效的指针地址

重点煤矿:


  

(C99,6.5.6p8)如果指针操作数和结果指向相同的数组对象的元素,或者一个过去的数组对象的最后一个元素都,该评估也不得产生溢出; 否则,行为是不确定的。


I found this problem in a very large application, have made an SSCCE from it. I don't know whether the code has undefined behavior or -O2 breaks it.

When compiling it with gcc a.c -o a.exe -O2 -Wall -Wextra -Werror it prints 5.

But it prints 25 when compiling without -O2 (eg -O1) or uncommenting one of the 2 commented lines (prevent inlining).

#include <stdio.h>
#include <stdlib.h>
// __attribute__((noinline)) 
int f(int* todos, int input) {
    int* cur = todos-1; // fixes the ++ at the beginning of the loop
    int result = input;
    while(1) {
        cur++;
        int ch = *cur;
        // printf("(%i)\n", ch);
        switch(ch) {
            case 0:;
                goto end;
            case 1:;
                result = result*result;
            break;
        }
    }
    end:
    return result;
}
int main() {
    int todos[] = { 1, 0}; // 1:square, 0:end
    int input = 5;
    int result = f(todos, input);
    printf("=%i\n", result);
    printf("end\n");
    return 0;
}

Is GCC's option -O2 breaking this small program or do I have undefined behavior somewhere?

解决方案

int* cur = todos-1;

invokes undefined behavior. todos - 1 is an invalid pointer address.

Emphasis mine:

(C99, 6.5.6p8) "If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined."

这篇关于是gcc的选项-O2打破这个小程序还是我具有不确定的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆