在.NET中的CLR上下文中,如何分配堆栈空间以及它通常受限于什么?
例如:
在内存耗尽之前,任何给定的线程都可以继续添加到堆栈吗?如果不; CLR如何决定分配多少空间并改变主意呢?
PS:只是为了给它设置一些上下文,这一切都始于讨论如何构建一个计算Fibonacci序列的方法,其中一个建议是一个递归函数。答案 0 :(得分:4)
CLR会立即为每个线程提交完整的堆栈空间。默认堆栈大小为1MB。如果你将堆栈超过那个大小,那就是堆栈溢出并引发错误。
CLR采用与本机代码不同的策略,仅保留1MB但按需提交。
这些是实施细节。最好只将堆栈视为固定大小的数据结构。此视图适用于.net和本机堆栈实现。
递归函数是计算Fibonacci的绝对最差方法,因为它的复杂性是指数级的。相反,你应该使用迭代算法,该算法在时间上是线性的,在空间中是常数。例如:
static int fib(int n)
{
int result = 0;
int a = 1;
for (int i=1; i<=n; i++)
{
int temp = result;
result = a;
a = temp + a;
}
return result;
}
当然,实际上,在到达堆栈溢出之前很久就会溢出结果变量。但是对于30-40范围内的n
值,递归算法的性能是站不住脚的。
另一种明智的方法是用预先计算的值填充静态数组。同样,由于值增长如此之快,因此您不需要非常大的数组来包含适合int
甚至long
的所有值。