C# - 垃圾回收

标签 c# heap-memory stack-memory

好的,我了解了栈和堆(值存在于栈中,引用存在于堆中)。

当我声明一个类的新实例时,它位于堆上,并在堆栈上引用内存中的这一点。我也知道 C# 有它自己的垃圾收集器(即它确定实例化类何时不再使用并回收内存)。

我有两个问题:

  1. 我对垃圾收集的理解是否正确?
  2. 我可以自己做吗?如果是的话,我自己这样做有什么真正的好处,还是我应该放弃它。

我问是因为我在 For 循环中有一个方法。每次我经历一个循环时,我都会创建我的类的一个新实例。在我的脑海中,我想象所有这些类都堆成一堆,除了占用内存之外什么都不做,我想尽快摆脱它们以保持整洁!

我理解正确还是我遗漏了什么?

最佳答案

Ok so I understand about the stack and the heap (values live on the Stack, references on the Heap

我认为您不了解堆栈和堆。如果值存在于堆栈中,那么整数数组存在于何处?整数是值。您是在告诉我整数数组将其整数保存在堆栈中吗?当你从一个方法返回一个整数数组时,比如说,其中有一万个整数,你是在告诉我那一万个整数被复制到堆栈上了吗?

值活在栈上就活在栈上,活在堆上就活在堆上。事物的类型其存储的生命周期 有关的想法是无稽之谈。 生命周期短的存储位置进入堆栈; 长期存在 的存储位置位于堆中,并且与它们的类型无关。长生命周期的 int 必须放在堆上,就像类的长生命周期实例一样。

When I declare a new instance of a Class, this lives on the heap, with a reference to this point in memory on the stack.

为什么引用必须入栈?同样,引用存储的生命周期与其类型无关。如果引用的存储是长期存在的,那么引用会进入堆。

I also know that C# does it's own Garbage Collection (ie. It determines when an instanciated class is no longer in use and reclaims the memory).

C# 语言不这样做; CLR 会这样做。

Is my understanding of Garbage Collection correct?

你似乎相信了很多关于堆栈和堆的谎言,所以很有可能不,事实并非如此。

Can I do my own?

不在 C# 中,不。

I ask because I have a method in a For loop. Every time I go through a loop, I create a new instance of my Class. In my head I visualise all of these classes lying around in a heap, not doing anything but taking up memory and I want to get rid of them as quickly as I can to keep things neat and tidy!

垃圾收集的全部意义在于让您不必担心整理问题。这就是为什么它被称为“自动垃圾收集”。它为您整理。

如果您担心循环会产生收集压力,并且出于性能原因希望避免收集压力,那么我建议您采用池化策略。从显式池化策略开始是明智的;即:

while(whatever)
{
    Frob f = FrobPool.FetchFromPool();
    f.Blah();
    FrobPool.ReturnToPool(f);
}

而不是尝试使用复活终结器进行自动池化。我一般建议不要使用终结器和对象复活,除非您是终结语义方面的专家。

如果池中没有 Frob,池当然会分配一个新的 Frob。如果池中有一个 Frob,则将其分发出去并将其从池中移除,直到它放回池中。(如果您忘记将 Frob 放回池中,GC 最终会找到它。)通过追求池化策略让 GC 最终将所有 Frob 移动到第 2 代堆,而不是在第 0 代堆中产生大量收集压力。然后收集压力消失,因为没有分配新的 Frobs。如果其他原因产生收集压力,Frob 将全部安全地放在很少访问它们的第 2 代堆中。

这当然与您描述的策略完全相反;池策略的全部要点是让对象永远停留。如果您打算使用对象,则对象永远卡在周围是一件的事情。

当然,在您通过分析知道由于收集压力而存在性能问题之前,请勿进行此类更改!在桌面 CLR 上很少有这样的问题;它在紧凑型 CLR 上更为常见。

更一般地说,如果您是那种让内存管理器按计划为您清理感到不舒服的人,那么 C# 不适合您。请考虑使用 C。

关于C# - 垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8730451/

相关文章:

c - 解决错误 'Address of stack memory associated with local variable returned'

c# - 如何按 List<int> 对 List<Type> 进行排序?

c# - 如何配置我的设置文件以使用单元测试?

c - 如何在 C 中释放二维数组内存

search - 如何在不指示 "top n"命中限制的情况下搜索 Lucene.NET?

x86 - 我可以从堆栈中弹出一个值,但将它放在 NASM Assembly 的任何地方吗?

c# - 欺骗应用程序关于鼠标位置的信息

c# - 从具有不同 <T> 的通用列表中随机选择

java - Integer对象的内存地址

删除数组时检测到 C++ 堆损坏