我试图了解是什么优化过程导致以下代码在使用-O3优化标志编译时产生无限循环。为了解决这个问题,我了解到问题的真正根本原因是这个非空函数中缺少返回,我在嵌入式系统上实现这段代码的过程中遇到了这个有趣的行为,并且还没有添加返回值,因为我没有使用返回值在那一点。
我的问题更多的是关于优化过程,以及它所做的任何事情在其他情况下如何帮助/“优化”的逻辑是什么样子的。
对于更多的上下文,我在使用ubuntu中的c编译器(c(Ubuntu 9.4.0- 1ubuntu 1 ~20.04.1)9.4.0)以及Xilinx Vitis 2020.2附带的aarch 64-linux-gnu-g++编译器(当然,在它们各自的平台上运行)时都看到了这种行为。
最小可复制示例(我目前已创建):
#include <iostream>
int broken_for_loop(){
for (int i = 0; i < 10000; i+= 1000){
std::cout << i << std::endl;
}
}
int main(int argc, char const *argv[]){
broken_for_loop();
}
当用c++ ./broken_loop_test.cpp -o test_local -O3
或ARM equiv编译时,循环的输出是无限的,我一直运行它,直到32 b int回绕。如果没有优化,它会像我预期的那样工作。如果我在for循环后简单地使用return 0
,它也会在优化下工作。
我天真地怀疑,因为循环外没有返回,编译器预期我将从循环内返回或中断,因此删除了将测试循环条件的检查/分支,但我想知道我可以研究什么来获得有关此特定主题的更多信息(和一般的优化,自从我上一次学习编译器设计课程以来已经有一段时间了),我对ASM还不够熟悉,无法自信地确定其中的问题。
任何帮助都将不胜感激,谢谢!
因为这一节是必需的,我会注意到我尝试过声明volatile i
,使用不同类型的整数,以及转换常量值,并在循环中做更多/更少的事情。所有这些都导致了相同的行为,而没有返回语句。
1条答案
按热度按时间pgvzfuti1#
Undefined behaviour results in time travel。
您的代码就是一个很好的例子。
在循环之后有未定义的行为(一个必须返回值的函数没有)。因为编译器可以假设UB永远不会发生,所以它假设循环永远不会终止,并相应地编译它。