【发布时间】:2011-06-19 00:26:42
【问题描述】:
所以我在玩一些思想实验,我想象当两个函数相互递归时会发生什么。如果两个函数都可能陷入无限循环,其中之一就是这样。
为此,我想到了这个简单的例子:
#include <iostream>
#include <cstdlib>
int foo(int x);
int bar(int x);
int foo(int x)
{
return bar(x + 1);
}
int bar(int x)
{
return foo(x - 1);
}
int main(int argc, char **argv)
{
if (argc > 1)
std::cout << "The value is: " << foo(atoi(argv[1])) << std::endl;
return 0;
}
有趣的是,如果你用 g++ 编译它,它实际上不会打印任何东西。使用任何-O开关编译它,它就会陷入无限循环。
想法?这可能是编译器错误,还是可以预料到的?我认为在 -O 优化的情况下,它会意识到 foo(x) 和 bar(x) 只返回 x。
我没想到它实际上会“优化”调用并完全忽略将“值是”打印到标准输入。
编辑:我在 Cygwin 下使用 GCC 4.5.0 将它编译为 g++ source.cpp (-O1/2/3)。 -OX 版本实际上无限循环而不会溢出堆栈。
【问题讨论】:
-
如果它没有永远循环,我会相当惊讶。
-
@delnan:然而,这正是他所说的,没有优化。
-
它出现段错误,因为计算机没有无限堆栈。如果不进行优化,此递归将溢出堆栈。优化器无法确定此递归的头或尾除了,它可以看到如何将这些函数调用更改为跳转。在这种情况下没有堆栈溢出,因为优化器已将这些递归函数更改为递归协程。无论哪种方式,它都是未定义的行为。
-
“-OX 版本实际上无限循环,堆栈不会溢出。” # 你测试过它吗?
-
@Tomalak:我查看了程序集(i686-apple-darwin10-g++-4.2.1)。编译器将这些函数调用更改为带有 -O2 或更高版本的跳转。如果栈上没有操作,栈怎么会溢出?
标签: c++ recursion mutual-recursion