【问题标题】:Is stack memory only for pointers and heap for objects?堆栈内存是否仅用于指针和堆用于对象?
【发布时间】:2017-01-17 18:04:17
【问题描述】:

首先,我目前正在使用 C#,并且一直在阅读有关内存管理的内容。到目前为止,我已经阅读了一些关于堆栈溢出的精彩答案,解释了堆栈内存和托管堆内存之间的区别。大多数答案表明,通过声明:
int x = 5,您为堆栈内存中的x 类型分配了足够的内存。

我了解它的工作原理以及它的范围,但是当我阅读堆内存的解释时,它让我感到困惑。

如果你说int x = 5,因为intSystem.Int32 的别名,那么x 在技术上不是指向System.Int32 结构的新实例的指针吗?如果是这样,它不会存储在堆内存中,因为它用于实例对象。

this 教程中,它指出(对于class1 cls1 = new class1() 行):

... 在堆栈上创建一个指针,实际对象存储在称为“堆”的不同类型的内存位置中。

按照这个逻辑,不是所有的东西都存储在堆上,而只有指针存储在堆栈上吗?例如System.StringSystem.Int64System.BooleanSystem.Decimal 等的新实例。

我以为我明白了,但很明显我不明白,所以我很感激有人解释堆栈是否仅用于指针或我误解了哪一部分。提前致谢。

【问题讨论】:

  • System.Int32 是一个结构,而不是一个类。因此,作为本地,它很可能会在堆栈上分配。
  • 请记住,.NET CLR 正在发生变化,“堆分配”和“堆栈分配”之间的界限越来越模糊。
  • 教程错误且不完整。
  • @Nathangrad 结构在 C# 中不能为空。结构是值类型。没有引用为空。 C# 编译器可能会因“使用未初始化的变量”而出错,但这只是编译器试图提供帮助。

标签: c# pointers memory heap-memory stack-memory


【解决方案1】:

您可以使用以下规则:如果它是结构体(包括原始类型),则在声明的位置分配,否则分配指向堆中对象的指针。

可能的位置是:

  1. 对于局部变量,它是一个堆栈。请注意,物理值可以存储在 CPU 寄存器中,而不是堆栈中。
  2. 对于类字段,它位于为类实例在堆中分配的连续内存块内。
  3. 对于静态字段,它作为类型元数据的一部分在加载器堆中分配(如果我错了,请纠正我)。

警告:这只是基本的、非全面的解释,以便对正在发生的事情有一个基本的了解。现实更加复杂。局部变量可以被提升并移动到堆中,优化器可以完全消除它们,等等......

【讨论】:

  • 对于unhoisted局部变量,可能是栈。如果您想准确一点,请参阅 cmets 中链接到的 Eric Lippert 帖子。
  • 是的,被提升的变量变成了显示(闭包)类的字段
  • 即使变量没有被提升,堆栈也可能不会被使用。它可以严格使用寄存器,也可以完全优化。
  • 我只需要谷歌搜索您在答案中使用的 80% 的技术术语,但我想我明白了。谢谢!
【解决方案2】:

您可能需要查看Classes and structs (MSDN) 以了解存储内容的位置和方式:

int x = 1; // 32 bits holding an integer in the stack
System.Object bo = x; // 32+some more bits are on the heap to hold the "boxed" (wrapped to be kept on the heap) integer value
System.Object ho = new Object(); // some bits are created on the heap right from the start

简单来说,有两种类型的对象:类和结构。类(引用类型)旨在存储在堆上并具有指向它们的指针,而结构则旨在存储在堆栈中(结构可以重新定位到堆,尽管有一点包装(“装箱” ) 他们)。

如果您确实需要/想了解 CLR 的一般工作原理,请考虑阅读“CLR via C#”(Richter)。

【讨论】:

  • 如果你有很多空闲时间,你可以阅读ECMA规范。
  • 如果你想添加更多,你应该编辑你的答案。永远不需要直接对自己的评论(问题/答案)
  • 这比“值类型存储在堆栈上,引用类型存储在堆上”更复杂。
  • classes [...] have a pointer to them in the stack 指针不一定在堆栈上。它可能在堆栈上,适用于 any 值,正如 Joshua 还指出的那样,它也会使同一句子的后半部分出错。
  • 正如我(和 Joshua)之前所说,句子的其余部分仍然是错误的。
猜你喜欢
  • 2023-03-17
  • 2021-08-22
  • 2021-06-28
  • 2012-09-16
  • 2020-09-02
  • 2013-08-19
  • 2012-10-07
  • 2017-09-24
  • 2019-10-23
相关资源
最近更新 更多