【问题标题】:How does a new statement allocate heap memory?new 语句如何分配堆内存?
【发布时间】:2010-07-16 04:40:58
【问题描述】:
private button btnNew=new button();
btnNew.addclickhandler(this);
private DataGrid grid;
private void onClick(event click) {grid=new DataGrid();}

你好,我写了一个类似这个示例的代码,我想知道每次用户点击btnNew时,堆和堆栈内存中发生了什么?例如,堆内存中的一个新块是否分配给这个grid?或者一个旧块被移除并且这个新块替换它?或者一个旧块保留在堆内存中并且新块分配给它。

这段代码是否在几次点击时分配了巨大的内存? **DataGrid 可以替换为我想知道的关于这种类型的新语句使用和内存分配的任何组件** 对不起,我的英语不好!

.

【问题讨论】:

  • @Michael Petrotta:想合并我们的两个编辑吗?我不想太快把它扔进 wiki 模式。
  • 您回滚我们的编辑有什么特别的原因吗?我们只是想让您的问题变得更好。
  • 我知道 mmyres tnx 需要您注意,但我知道我犯了错误,所以我更正了我的问题。

标签: c# memory memory-management dynamic-memory-allocation


【解决方案1】:

关于堆的情况 和堆栈内存?

由于按钮是引用类型并在全局中声明,因此将在堆中分配,而不是在堆栈中。

堆内存中是否有新块分配给此按钮?

如果内存可用,是的,否则将删除未到达的引用并分配此引用

这段代码是否分配了一个 单个内存大 点击?

不,但如果你添加一千个按钮,它会

查看Jon Skeet 撰写的这篇很酷的文章Memory in .NET - what goes where,以更好地了解内存内部结构..

干杯

【讨论】:

  • 看来我投了反对票,但我不记得这样做了,因为我没有阅读您的帖子。也许是一个不小心的点击导致了这种情况。请编辑您的答案,以便我可以删除此反对票。更好的是,在阅读了您的回答后,我相信您应该投赞成票。
【解决方案2】:

这是一个巨大的话题。这类似于询问“您在浏览器中输入 www.amazon.com。接下来会发生什么?”要完全回答这个问题,您必须解释整个互联网的架构。要完全回答您的问题,您必须了解现代操作系统的整个内存模型。

您应该从阅读内存和垃圾收集的基础知识开始,这里:

http://msdn.microsoft.com/en-us/library/ee787088.aspx

然后就你不明白的事情提出更具体的问题。

【讨论】:

  • @EricL-谢谢你,我读了这篇文章,它对我很有用。我忘了说这个对象是 ref 类型的。
【解决方案3】:

使用 new 语句在堆上分配内存。通常分配新的内存。如果 btnNew 指针是唯一与按钮对象关联的指针,它应该成为垃圾收集器的目标。所以内存将再次被释放。多次点击也会发生同样的情况,但您应该知道垃圾收集器不会实时工作。因此,在分配大对象的高频循环中——“new”可能会成为 c# 中的一个问题。

【讨论】:

  • new 与引用类型一起使用会在堆上分配内存。如果你 new 一个结构体,它会被分配到栈中。
  • @Brian:值类型上的“new”首先不会分配存储空间,并且值类型的存储空间不需要在堆栈上。
  • @Eric:你说得对,我的措辞不够具体。谢谢。
  • @Eric:我的意思是new 不一定在堆上分配内存。本地值类型存储在堆栈中,在这种情况下,new 只是调用我理解的构造函数。
【解决方案4】:

如果按钮是一个类(引用类型),它被分配在堆上。 (在当前 CLR 实现中,值类型在堆栈上分配,除非它们被另一个引用类型包含或在闭包中捕获 - 在这种情况下,它们在堆上。)。

垃圾收集器预先分配了不同大小的内存段,对应于第 0 代、第 1 代和第 2 代。当你新建一个对象时,它会在第 0 代分配。而且这种分配非常快,因为它只是将指针移动 delta = 对象的大小。 CLR 在执行 ctor 之前将对象中的值清除为默认值作为先决条件。

定期暂停所有线程并运行垃圾收集器。它通过遍历“根”来创建可达对象的图。所有无法访问的对象都被丢弃。生成段被移动/压缩以避免碎片。 Gen 0 比 1 更频繁地被收集,依此类推......(因为 Gen-0 对象可能是短期对象)。收集后,应用线程恢复。

有关这方面的更多信息,请参阅说明垃圾收集器和生成的文档。这里是one

【讨论】:

  • 值类型不在堆栈上分配。正确的说法是,作为局部变量或临时存储的值类型,使得局部变量不是匿名方法或 lambda 表达式的封闭外部局部变量或迭代器块的提升局部变量,存储在 Microsoft 实现的堆栈中C# 在桌面 CLR 上运行。作为引用类型字段或提升的局部变量的值类型变量存储在堆上。 any 实现不需要在“堆栈”上存储任何内容。堆栈是一个实现细节。
  • 当然,在运行时,可能根本不会分配值类型。可以注册等于或小于寄存器大小的值类型,这意味着它们既不存储在堆上也不存储在堆栈上。
  • @EricL - 感谢更新我的答案。我的回答并不准确(关于包含的值类型不在堆栈上),因为原始问题并未表明 OP 对值类型感兴趣。但是,它可能会被其他读者误解……所以编辑我的帖子以包含此内容。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-06-17
  • 2020-10-05
  • 1970-01-01
  • 2020-11-09
  • 2013-05-09
  • 1970-01-01
  • 2023-03-06
  • 2010-10-10
相关资源
最近更新 更多