【问题标题】:Infinite recursion without overflow - is it possible?无限递归没有溢出 - 有可能吗?
【发布时间】:2014-04-20 20:32:51
【问题描述】:

堆栈溢出的原因是堆栈空间用完了,但是如果函数没有参数,因此不必将数据压入堆栈怎么办?这仍然会推动“返回”地址,但在 预期 无限递归的情况下,这是不必要的。

所以我想问的是......是否可以使用某种调用约定,即调用不会将任何东西放在堆栈上,只是跳转到第一条指令并执行,并提供最后的指令将是对函数的另一个调用,直到最终终止执行?理想情况下,这是否可以通过函数指针和动态链接来实现?

只是为了说明,我指的是一个接受单个参数并且不返回任何内容的函数,因此从技术上讲 fastcall 就足够了,但它仍然保留了要返回的地址,这最终会导致溢出。可以通过某种方式防止这种情况发生吗?

我之前没有提到的另一个重要点,我不是指单个函数的递归,例如在状态是静态且正在被重用的情况下,我的意思是从一个任意函数递归到另一个函数。

【问题讨论】:

  • 据我所知不在 C++ 中.. 你需要 C++/C 目前不支持的 Tail Recursion(至少作为标准的一部分)
  • 我不认为有 is 没有将任何内容放入堆栈的调用约定。 MSDN's calling-convention docs 展示了一堆不同的调用约定,但最终都使用堆栈(少数先使用寄存器)。
  • 为了澄清@Mgetz 的评论,C 和 C++ 标准都不需要支持尾调用,但它们都允许,并且当前的编译器能够支持。
  • 采用单个参数”,如果不在堆栈上,应该存储在哪里?
  • @alk 这将是实现它的一种方法,但很可能编译器只是将函数体更改为循环,而不需要递归调用。实现尾递归并不难,难的是检测它适用的情况。

标签: c++ c recursion stack-overflow calling-convention


【解决方案1】:

是的,有两种可能的递归函数。您正在寻找的那种是primitive recursive functions,它们相当于一个简单的循环。并且通常使用tail recursion 实现,其中堆栈保持不变,并且函数永远不会通过堆栈返回。

一些C++ compilers 可能能够检测到一些原始递归函数,并将它们转换为循环构造而不是函数调用。但这只有在编译器能够识别正在发生的事情时才有效。所以答案也许是。基本上,如果程序员做了一些非常无效的事情,那么编译器可能会也可能不会提供帮助。所以通常的“编码、配置、优化、重复”过程仍然进行。

【讨论】:

  • 1+,刚刚测试过,它似乎确实有效。 :-)
  • +1 提到“尾调用优化”,因为它是每个函数式编程语言在教程中的答案和基本内容
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 2018-03-25
  • 2014-03-19
  • 2012-07-08
  • 2017-09-05
  • 1970-01-01
  • 2010-10-21
相关资源
最近更新 更多