【发布时间】:2020-01-13 07:01:39
【问题描述】:
以下代码在使用g++ -O3 .. 和不使用-O3 编译时具有不同的行为。
我知道updateError 没有返回任何内容,这可能导致未定义的行为。我不明白的是,如果使用 -O3 编译,error 在循环内设置为零,if(error > eps) 被评估为 false,而在 while() 语句中仍被评估为 true。 .
我还尝试将其更改为 do{}while() 循环,在这种情况下它也适用于 -O3...
#include <stdio.h>
using namespace std;
double updateError(){
printf("updating Error\n");
}
int main(int argc, char *argv[]){
double eps = 1.e-10;
double error = 2*eps;
int iter = 0;
while(error > eps){
error = updateError();
iter++;
printf("Error on iteration %i: %.20e\n", iter, error);
if(error > eps) printf("error bigger\n\n");
else printf("error smaller\n\n");
if(iter == 5){
printf("not converged in 5 iterations!!\n");
break;
}
}
return 0;
}
使用 -O3 的控制台输出:
updating Error
Error on iteration 1: 0.00000000000000000000e+00
error smaller
updating Error
Error on iteration 2: 0.00000000000000000000e+00
error smaller
updating Error
Error on iteration 3: 0.00000000000000000000e+00
error smaller
updating Error
Error on iteration 4: 0.00000000000000000000e+00
error smaller
updating Error
Error on iteration 5: 0.00000000000000000000e+00
error smaller
not converged in 5 iterations!!
没有 -O3 的控制台输出:
updating Error
Error on iteration 1: 6.92743341769227318242e-310
error smaller
【问题讨论】:
-
这不是“它会导致未定义的行为”。 这是未定义的行为。允许编译器对代码执行任何操作,尤其是在优化代码时。
-
我知道 updateError 没有返回任何东西,这可能导致未定义的行为不能,但 会。在包含 UB 的情况下分析您的代码是没有意义的。由于执行路径遇到了UB,你的整个程序就变成了UB,任何事情都可能随时发生。
-
您可能想要检查生成的程序集并将优化的构建与未优化的构建进行比较。一个很好的方法是通过compiler explorer site。可以看出,可能会有很大的不同!
-
在我的系统上,输出是
runtime error: execution reached the end of a value-returning function without returning a value -
您明确地编写了一个未定义的行为,并提出了一个问题,即为什么程序的行为不像您所期望的那样。 UB 意味着你不能期待任何事情(或者换句话说,任何事情都可能发生)。这个问题听起来像“我有一个玩具,我用锤子把它弄坏了。你能解释一下为什么它现在坏了吗?” :)
标签: c++ gcc optimization while-loop evaluation