Iva*_*vic 0 c++ recursion function
我正在学习 C++ 以及来自 Alex Allain 的“Jumping into C++”的其他书籍,并且正在学习递归。有一个程序示例可以计算出我的计算机可以处理多少递归,直到出现“堆栈溢出错误”或在我的情况下出现“分段错误”。
在使用给定的示例代码之前,我编写了一个简短的程序来测试它,它表明我的代码可以处理比给定的示例代码多一倍的递归。我的问题:为什么会这样,因为它几乎是相同的模式 - 一个函数调用自身并迭代一个整数。
第二,为什么会出现分段错误而不是堆栈溢出?
我真的很想了解 C++ 编程,并希望能够编写使用少量系统资源的“廉价”程序,这确实是必要的。
我的代码:
#include <iostream>
using namespace std;
int i = 1;
void recurse ()
{
i = i + 1;
cout << "number: " << i << endl;
recurse();
}
int main()
{
recurse();
}
Run Code Online (Sandbox Code Playgroud)
本书中的代码示例:
#include <iostream>
using namespace std;
void recurse(int count)
{
cout << count << endl;
recurse(count + 1);
}
int main()
{
recurse(1);
}
Run Code Online (Sandbox Code Playgroud)
我的输出: 我系统上两个示例的输出屏幕截图,以查看我所指的差异
使用编译器 Linux g++ -std=c++17 (Arch Linux)
两个版本的代码都有未定义的行为。编译器可以很容易地证明该recurse函数会无限递归,并且最终也会出现整数溢出。
C++ 标准明确表示对具有未定义行为的程序的行为没有限制。您可能会遇到堆栈溢出、分段违规、您的硬盘驱动器可能被格式化、可能发射核导弹、恶魔可能从您的鼻子里飞出、程序可能什么都不做,或者(最糟糕的是)它可能不小心做了什么你自找的。
因此,使用具有未定义行为的 C++ 程序来测试系统的限制或多或少毫无意义。
如果您删除输出,请参阅此处了解两个编译器如何在优化下转换您的代码:https :
//godbolt.org/z/Lqln9n
请注意如何clang查看未定义的行为并将其替换为“什么都不做并返回”。你不会在那个编译器上崩溃,程序什么都不做!而 MSVC 将无限递归优化为一个简单的无限循环 ( loop: jmp loop)。它会永远重复这条指令,而不是得到警告中提到的堆栈溢出。
混合输出后,编译器可能会再次做不同的事情。但在每种情况下,除了“编译器决定这样做”之外,运行程序并没有得到任何有意义的答案。您可以检查生成的汇编代码(见上文)以查看编译器做了什么,然后使用它来解释您看到的行为。但我必须重申,给定的 C++ 代码没有定义的行为,可能会做任何事情。
| 归档时间: |
|
| 查看次数: |
81 次 |
| 最近记录: |