为啥在 C# 参考文本中引用堆栈和堆?

Posted

技术标签:

【中文标题】为啥在 C# 参考文本中引用堆栈和堆?【英文标题】:Why are Stack and Heap cited on C# reference texts?为什么在 C# 参考文本中引用堆栈和堆? 【发布时间】:2020-10-25 10:00:27 【问题描述】:

据我所知,堆栈和堆的概念在应用于内存时是指用于管理内存的数据结构。

如果这些是语言(即 C#)未强制执行的抽象术语,并且存在未使用此类概念实现内存虚拟化的设备和系统;那么为什么基本上每本书或参考文本都使用这两个术语来解释自动和动态数据分配?这些文本不应该使用更抽象的概念来解释数据分配吗?

【问题讨论】:

你读过吗,例如this question on the stack/heap? @Putnam 是的,我有。为什么? "如果这些是语言不强制执行的抽象术语" 在这种情况下,这是错误的假设。 C# standard 明确引用“heap”和“stack”。实际上有一个stackalloc 关键字。 @underthevoid 你有运行 C# 的例子吗?假设这样的系统需要模拟预期的堆和堆栈行为以符合标准。 CPU栈和堆不是抽象的东西,而是物理的东西。除非我们将堆栈作为一种数据结构来讨论并且那里没有堆,这不是一回事,只有堆栈的概念是共享的。否则,栈和堆和其他事物一样,都是抽象概念……人类大脑通过生产 CPU 和编程语言创造并实现了这些概念。 【参考方案1】:

我从未阅读过 C# 规范,但早在该语言于 2002 年发布之前,我就一直在使用它。

堆栈和堆可能是抽象的,但 C# 的 .NET 实现包括

托管内存堆。引用类型的分配(使用new)导致从该堆分配内存(概念上只有一个堆,正常实现使用多个)。这个堆由垃圾收集器管理——对这个堆的引用被跟踪,当一个分配在这个堆上的对象不再有任何引用时,它就有资格被收集。这一切的工作原理是一个实现细节,但这个概念是必需的。

函数调用需要一个地方来存储返回地址和调用参数。并非所有机器架构都将这些存储在堆栈中(尽管我认为我所见过的每个架构都包含一个堆栈,多余的调用参数(超过可以在寄存器中传递的参数)将溢出进入)。

局部变量(值类型变量和对引用类型实例的引用)需要一个存放位置。它们的作用域绑定到函数调用的生命周期。它们也倾向于存储在堆栈中。

值得注意的是,并非所有 local 值类型变量现在都驻留在堆栈中。随着闭包中捕获的变量和async 函数的出现,编译器可以做一些魔术;将看似局部的值类型变量存储在隐藏类的实例中。

【讨论】:

那么标准中引用的堆总是指由CLR创建和维护的完全托管的堆?关于假设堆栈的引用呢?该标准是否暗示必须有一个操作系统级别的堆栈?生成的 CIL 具有修改堆栈的指令 - 该 CIL 是否依赖 CLR 知道在运行时要做什么?提前感谢您的回答!

以上是关于为啥在 C# 参考文本中引用堆栈和堆?的主要内容,如果未能解决你的问题,请参考以下文章

c#语法复习总结-数据类型

为啥会有栈和堆?

在 C++ 中正确使用堆栈和堆?

为啥文本框文本没有从 C# 中的起始位置显示?

堆栈和堆的内容和位置是什么?

Swift 栈和堆的理解