在 .NET 中的 CLR 上下文中,堆栈空间是如何分配的
在 .NET 中的 CLR 上下文中,堆栈空间是如何分配的以及它通常受到什么限制?
例如:
任何给定的线程都可以继续添加到堆栈中,直到内存耗尽吗?如果不; CLR 如何决定分配多少空间以及它可以改变主意吗?
PS:为了提供一些背景信息,这一切都是从关于如何构建计算斐波那契数列的方法的讨论开始的,其中一个建议是递归函数。
In the context of the CLR in .NET how is stack space allocated and what is it typically limited by?
For example:
Can any given thread continue to add to the stack until memory runs out? If not; how does the CLR decide how much space to allocate and can it change its mind?
PS: Just to put some context on it this all started from a discussion on how to build a method that will calculate the Fibonacci sequence and one of the suggestions was a recursive function.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
每个线程一创建,CLR 就会立即为每个线程提交完整的堆栈空间。默认堆栈大小为 1MB。如果将堆栈推入超过该大小,则会发生堆栈溢出并引发错误。
CLR 采用与本机代码不同的策略,本机代码仅保留 1MB,但按需提交。
这些是实施细节。最好简单地将堆栈视为固定大小的数据结构。此视图适合 .net 和本机堆栈实现。
递归函数绝对是计算斐波那契最差的方法,因为它的复杂性是指数级的。相反,您应该使用时间线性且空间恒定的迭代算法。例如:
当然,实际上,在堆栈溢出之前很久,您就会溢出结果变量。但对于
n
的值在 30-40 范围内,递归算法的性能是站不住脚的。另一种明智的方法是用预先计算的值填充静态数组。同样,由于值增长得如此之快,因此您不需要一个非常大的数组来包含适合
int
甚至long
的所有值。The CLR immediately commits the full stack space for each thread, as soon as it is created. The default stack size is 1MB. If you push your stack over that size, that's a stack overflow and an error is raised.
The CLR adopts a different policy from native code which merely reserves 1MB but commits it on demand.
Those are implementation details. It is best to simply view the stack as a fixed size data structure. This view fits with both .net and native stack implementations.
A recursive function is the absolute worst way to calculate Fibonacci because its complexity is exponential. Instead you should use an iterative algorithm which is linear in time and constant in space. For example:
Of course, in reality, you'd overflow your result variable long before you reached a stack overflow. But the performance of a recursive algorithm is untenable for values of
n
in the region of 30-40.Yet another sensible approach is to fill a static array with pre-calculated values. Again since the values grow so fast you don't need a very large array for it to contain all values that fit into an
int
or even along
.