为什么int main(){return main();导致stackoverflow而不是尾递归?

时间:2016-05-18 18:35:21

标签: c gcc stack-overflow tail-recursion

使用GCC在Windows上编译。它立即与Exception Code: c00000fd崩溃。

编辑:尝试编译以下代码(用于可见输出)并导致stackoverflow。

#include<stdio.h>
int main(void)
{
printf("Hello World\n");
return main();
}

输出 -

>gcc trailORoverflow.c -o trailORoverflow.exe

Hello World
Hello World
Hello World
Hello World
Hello World
Hello World

它会持续打印Hello World并崩溃。

修改:未因O2O3-O1 -foptimize-sibling-calls优化而崩溃。

1 个答案:

答案 0 :(得分:2)

您显示的代码将无限调用main,因此会导致堆栈溢出。在任何函数的情况下都是如此,并且不是main特有的。每个函数调用堆栈帧都是在内存中创建的,并且当递归深入时会创建无限的这样的帧,您将获得堆栈溢出。

但是,如果您按照以下示例进行正确的基址终止,那么对于main中的递归调用,则会有一个有趣的事情。

int main (void)
{
  static int x = 100;

  if (x == 0)
  {
    return 0;
  }
  x--;
  printf ("%d\n", x);
  main ();
  return 0;
}

在C和C ++语言中递归调用main存在差异,我认为指出这一点很有意思。这是我写的post,我正在解释它。

C ++标准在

中谈论这些

第3.6.1节第3段

Recursive calls are permitted, except to the function named main. 

和第5.2.2节第9段

The function main shall not be used within the program. … … … 

我没有在C标准中发现任何此类限制。我在第6.5.2.2节第11段中对C99标准中的递归调用所发现的内容如下

Recursive function calls shall be permitted, both directly and indirectly through any chain of other functions. 

因此,在C语言中递归调用main是确定性的。但是根据C ++标准,不允许从任何函数调用main或递归。