Programming languages 为什么堆栈溢出仍然是一个问题?
这个问题多年来一直困扰着我,考虑到这个网站的名字,这就是我要问的地方 为什么我们程序员仍然有这个Programming languages 为什么堆栈溢出仍然是一个问题?,programming-languages,stack,memory-management,Programming Languages,Stack,Memory Management,这个问题多年来一直困扰着我,考虑到这个网站的名字,这就是我要问的地方 为什么我们程序员仍然有这个StackOverflow问题 为什么在每种主要语言中,线程堆栈内存都必须在线程创建时静态分配 我将在C#/Java的上下文中发言,因为我使用它们最多,但这可能是一个更广泛的问题 固定的堆栈大小会导致巨大的问题: 除非绝对确定递归的深度很小,否则无法编写递归算法。递归算法的线性内存复杂性通常是不可接受的 没有廉价的方法来启动新线程。您必须为堆栈分配巨大的内存块,以考虑线程的所有可能用途 即使不使用非
StackOverflow
问题
为什么在每种主要语言中,线程堆栈内存都必须在线程创建时静态分配
我将在C#/Java的上下文中发言,因为我使用它们最多,但这可能是一个更广泛的问题
固定的堆栈大小会导致巨大的问题:
- 除非绝对确定递归的深度很小,否则无法编写递归算法。递归算法的线性内存复杂性通常是不可接受的
- 没有廉价的方法来启动新线程。您必须为堆栈分配巨大的内存块,以考虑线程的所有可能用途
- 即使不使用非常深的递归,由于堆栈大小是一个任意的固定数字,您始终有耗尽堆栈空间的风险。考虑到StackOverflow通常是不可恢复的,在我看来这是一个大问题
ArrayList
这样的结构,而不会遭受太多的痛苦
所以,问题是,我是否遗漏了一些东西,堆栈溢出不是问题,或者我遗漏了一些东西,有很多语言使用动态堆栈,或者这是不可能实现/难以实现的重要原因
编辑:
有些人说,性能将是一个大问题,但请考虑如下:
- 我们保持编译后的代码不变。堆栈访问保持不变,因此“通常情况”性能保持不变
- 我们处理当代码试图访问未分配的内存并启动“重新分配”例程时发生的CPU异常。重新分配不会频繁,因为。应在大多数受保护模式的CPU上工作,而不会损失性能。没有
固定堆栈机制对于大多数应用程序来说都能很好地工作,所以没有必要去改变它。如果没有,您可以随时推出自己的堆栈。我个人从未遇到过不是由无限递归引起的堆栈溢出。在这些情况下,动态堆栈大小没有帮助,只是需要稍长的时间来耗尽内存。任何会在典型的静态长度堆栈上导致堆栈溢出的代码都是错误的
- 您可以将堆栈设置为类似std::vector的对象,但当它决定调整大小时,您的性能将极不可预测——而且无论如何,它很可能会一直这样做,直到所有堆都耗尽为止,这更令人恼火
- 你可以把它做成一个std::list,它在O(1)处增长。然而,在静态堆栈上使用的指针算法对程序性能的各个方面都非常关键,因此它的速度会非常慢。语言被发明为具有一个返回值和任意数量的输入参数,因为这符合静态堆栈/指针算术范式
#include <deque>
#include <iostream>
size_t fac(size_t arg){
std::deque<size_t> v;
v.push_back(arg);
while (v.back() > 2)
v.push_back(v.back() - 1);
size_t result = 1;
for (size_t i = 0; i < v.size(); i++)
result *= v[i];
return result;
}
int main(int argc, char** argv){
int arg = 12;
std::cout << " fac of " << arg << " is " << fac(arg) << std::endl;
return 0;
}