Stack overflow caused by recursive function(递归函数引起的堆栈溢出)
问题描述
我是 C++ 的初学者.昨天我读了递归函数,所以我决定自己写.这是我写的:
I'm a beginner in C++. Yesterday I read about recursive functions, so I decided to write my own. Here's what I wrote:
int returnZero(int anyNumber) {
if(anyNumber == 0)
return 0;
else {
anyNumber--;
return returnZero(anyNumber);
}
}
当我这样做时:int zero1 = returnZero(4793);
,它会导致堆栈溢出.但是,如果我将值 4792 作为参数传递,则不会发生溢出.
When I do this: int zero1 = returnZero(4793);
, it causes a stack overflow. However, if I pass the value 4792 as the argument, no overflow occurs.
对原因有什么想法吗?
推荐答案
无论何时调用函数,包括递归调用,返回地址和参数通常都会被推送到 调用堆栈.堆栈是有限的,因此如果递归太深,您最终会耗尽堆栈空间.
Whenever you call a function, including recursively, the return address and often the arguments are pushed onto the call stack. The stack is finite, so if the recursion is too deep you'll eventually run out of stack space.
令我惊讶的是,在您的机器上只需要 4793 次调用即可溢出堆栈.这是一个非常小的堆栈.相比之下,在我的计算机上运行相同的代码所需的调用次数是程序崩溃前的 100 倍.
What surprises me is that it only takes 4793 calls on your machine to overflow the stack. This is a pretty small stack. By way of comparison, running the same code on my computer requires ~100x as many calls before the program crashes.
堆栈的大小是可配置的.在 Unix 上,命令是 ulimit -s
.
The size of the stack is configurable. On Unix, the command is ulimit -s
.
鉴于该函数是尾递归,一些编译器可能能够通过将其关闭来优化递归调用进入跳跃.一些编译器可能会更进一步:当被要求进行最大优化时,gcc 4.7.2
将整个函数转换为:
Given that the function is tail-recursive, some compilers might be able to optimize the recursive call away by turning it into a jump. Some compilers might take your example even further: when asked for maximum optimizations, gcc 4.7.2
transforms the entire function into:
int returnZero(int anyNumber) {
return 0;
}
这正好需要两条汇编指令:
This requires exactly two assembly instructions:
_returnZero:
xorl %eax, %eax
ret
非常整洁.
这篇关于递归函数引起的堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:递归函数引起的堆栈溢出
基础教程推荐
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- C++,'if' 表达式中的变量声明 2021-01-01
- 设计字符串本地化的最佳方法 2022-01-01
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04