我在.NET中遇到了一些关于垃圾回收的好奇行为。在.Net中触发垃圾回收的标准
以下程序将非常快速地抛出一个OutOfMemoryException异常(在32位2GB计算机上不到一秒钟后)。 Foo终结器永远不会被调用。
class Foo
{
Guid guid = Guid.NewGuid();
byte[] buffer = new byte[1000000];
static Random rand = new Random();
public Foo()
{
// Uncomment the following line and the program will run forever.
// rand.NextBytes(buffer);
}
~Foo()
{
// This finalizer is never called unless the rand.NextBytes
// line in the constructor is uncommented.
}
static public void Main(string args[])
{
for (; ;)
{
new Foo();
}
}
}
如果rand.nextBytes行注释掉,它将运行循环往复,而富终结定期调用。这是为什么?
我最好的猜测是,在前一种情况下,无论是CLR还是Windows VMM都懒得分配物理内存。永远不会写入缓冲区,所以不会使用物理内存。当地址空间用完时,系统崩溃。在后一种情况下,系统在耗尽地址空间之前耗尽物理内存,触发GC并收集对象。
但是,这是我没有得到的部分。假设我的理论是正确的,为什么当地址空间不足时GC触发?如果我的理论不正确,那么真正的解释是什么?
我我不确定你是否有正确的答案,但是你让我走上了一条有趣的轨道。我关闭了两台运行的虚拟PC(均为512MB),并获得了您的行为。当我加载VPC时,我得到了最初的崩溃行为。 – 2010-04-19 22:16:13
在'GC'类中还有一些有趣的函数可以检出,但是在真实代码中这些函数永远不会被使用。 – 2010-04-19 22:18:04
当VPC运行并且Thread.Sleep(0)就位时,程序将永久运行。现在问题发生了变化......为什么在分配失败时GC不会自动触发? – 2010-04-19 22:18:11