下面的代码在使用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发布于 2019-09-11 20:35:01
我知道updateError没有返回任何东西,这可能导致未定义的行为。
没有“能”这个词。您的代码具有未定义的行为。句号。
在调试构建时,编译器会做一些额外的工作来增强调试器的使用。这可以是初始化变量之类的事情,而实际上它们并不是必须的。这样的开销在优化的构建中是不存在的。不管怎么说,如果你想知道为什么会得到这样的结果,你应该看看程序集。只需知道UB就是UB,所以您不能保证第二天使用相同的编译器会得到相同的结果。
我不明白的是,如果用-O3编译,那么在循环中错误被设置为零,如果(
> as )被计算为false,而在while()语句中它仍然被计算为true。。
请注意,您编写的代码不会逐行转换为CPU的指令。编译器相当聪明,在as-if规则下应用所有类型的转换。只要可观察到的行为是相同的,编译器就可以将您的代码转换为与简单的逐行转换完全不同的代码。然而,如果你的代码有UB,那么它就不是有效的c++代码,得到不同的输出和相同的变量也就不足为奇了。
https://stackoverflow.com/questions/57889116
复制相似问题