【问题标题】:Is the value of a C# decimal stored on the heap even when it is a local variable?C# 十进制的值是否存储在堆中,即使它是局部变量?
【发布时间】:2016-01-19 03:48:36
【问题描述】:

问题

当 C# decimal 是局部变量时,它的值是否存储在堆上?

我(相信)知道的事情

  • decimal 结构具有16 bytes
  • ValueType 类型的局部变量的值存储在堆栈中,decimal 继承自 ValueType
  • 在 32 位系统上,参考内存空间只有 4 个字节大;参考内存空间我的意思是下面标记的框,例如bazbar

    Image source.

  • 对于ValueTypes,这是存储值的位置;对于引用类型,这是存储 null 或对堆内存位置的引用的位置。

16 字节大的decimal 的值如何存储在堆栈中,而 32 位系统上只有 4 字节可用?

我的思路哪里出错了?

我读到的

【问题讨论】:

  • "在 32 位系统上,内存空间只有 4 个字节大。"你能告诉更多吗?
  • @codroipo:让我研究一下……
  • 堆栈变量可以大于 4 个字节。我认为您误以为它在 32 位系统上限制为 4 个字节。
  • Quote: 在32位系统上,内存空间只有4个字节大。你指的是什么内存空间???我想说:在 32 位系统上,指针的维度是 4 字节。即您只能寻址 2^32 个不同的内存位置。
  • 一个 reference 存在于堆栈中,在 32 位系统上是 4 个字节。这就是你的插图所显示的。但是,堆栈上的值类型几乎可以是任意大小。

标签: c# stack heap-memory


【解决方案1】:

在 32 位系统上只有 4 个字节可用的情况下,如何将 16 字节大的十进制值存储在堆栈中?我的思路哪里出错了?

您的想法在“32 位引用适合 4 个字节”的某处出现了错误,并由此得出结论“堆栈长 4 个字节”。堆栈默认为一百万字节长;如果运行时决定将十进制变量(或值)放入堆栈,那么它会保留这百万字节中的 16 个。

您正在考虑计算机如何在幕后工作是件好事,但当然不要忘记 C# 团队一直在努力开发一种语言,您不必关心变量是否在堆栈上或堆。您必须编写一些非常高级的程序才能发挥作用;我从未编写过需要担心堆栈与堆的业务线 C# 程序,而且我已经编写 C# 程序 10 多年了。

更新:

我更新了图片以说明我不认为整个堆栈有 4 个字节长,而只有一个引用“内存盒”。

好的,太好了。再一次,让我们假设一个引用是四个字节,在某些机器上它是。如果运行时需要在堆栈上放置一个引用,它会在堆栈上保留四个字节。没有要求将堆栈保留为四字节块。它可以保留在任何大小的块中。

所以我会更新我的解释。当您假设“引用是四个字节,因此堆栈只能保留在四个字节块中”时,您出错了。可以在堆栈上保留任意数量的字节,从零到一百万。

(请不要试图保留一百万;会发生不好的事情。.NET 指南要求创建 16 字节或更小的结构是有原因的!)

现在,出于性能原因,在某些架构上,运行时可能会尝试保留堆栈内存,以便每个块对齐到四字节边界。如果数据未对齐,某些硬件真的很慢。但这是您在 C# 中几乎不需要担心的细节级别。

再次更新:

这是另一种思考方式。假设我们有两个普通的局部变量,它们是 4 字节整数:

int x;
int y;

这会得到两个内存块,每个内存块是四个字节。现在假设我们有一个结构:

struct S 
{ 
    public int x; 
    public int y; 
}

我们创建一个局部变量:

S s;

和以前完全一样。我们堆栈上有两个变量,这些变量被命名为s.xs.y。将一个结构体放入堆栈,与将结构体中的所有字段变量都放入堆栈一样。

另一个更新:

另一件可能让您感到困惑的事情是,还有一种称为“寄存器”的临时存储,它也用于存储局部变量,而寄存器实际上只有四个字节长。 (除了那些是 8 的,但我们不要去那里。)一个 16 字节的结构如何存储在寄存器中? 不是。运行时根本不会将大结构放入寄存器中。

【讨论】:

  • 我更新了图片以说明我认为整个堆栈不是 4 个字节长,而是只有一个 reference “内存盒”。
  • @Lernkurve 关键是堆栈不是由 32 位块组成的,它由 8 位块(命名字节)组成,并且运行时可以免费使用其中的许多因为它需要适合值类型。仅仅因为引用类型在 32 位系统上使用了其中的 4 个,并不意味着没有什么可以使用更多。
  • @Kyle:谢谢!那是缺少的信息(现在也已在此答案中更新)。
  • @Lernkurve:我添加了一些更新来解决(哈哈)你更新的问题。
  • @EricLippert C# 的结构填充是否在这里发挥作用?我知道结构可以在某种程度上进行填充,但我对规则并不十分熟悉。这如何影响结构的可能大小以及允许的字边界不对齐程度?
猜你喜欢
  • 1970-01-01
  • 2017-11-05
  • 1970-01-01
  • 1970-01-01
  • 2015-04-18
  • 2019-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多