gpt4 book ai didi

.net - .Net 中触发垃圾收集的标准

转载 作者:行者123 更新时间:2023-12-03 21:33:39 24 4
gpt4 key购买 nike

关于.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 行未注释,它将无限运行,并且定期调用 Foo 终结器。这是为什么?

我最好的猜测是,在前一种情况下,CLR 或 Windows VMM 都懒得分配物理内存。缓冲区永远不会被写入,因此物理内存永远不会被使用。本地址空间用完时,系统崩溃。在后一种情况下,系统在地址空间用完之前就用完了物理内存,触发 GC 并收集对象。

但是,这是我不明白的部分。假设我的理论是正确的,为什么地址空间不足时 GC 不触发?如果我的理论不正确,那么真正的解释是什么?

最佳答案

代码在我的机器上以稳定的 18MB 运行,不管有没有这条线(XP SP3 x86、.Net 3.5 SP1、双核)。

您的机器上可能发生的情况是,当该行被注释时,程序大部分时间都在分配,并且在垃圾收集器线程有机会释放它之前设法分配了太多内存。当您取消注释该行时,程序花费的分配时间要少得多,因此在 GC 线程运行之前不能分配太多。

尝试用 Thread.Sleep(0) 替换注释行;如果它没有崩溃,我可能是正确的。

顺便说一句,您永远不应该依赖终结器 - 不能保证在对象被 GC 时立即调用它,甚至根本不保证。相反,在实际代码中实现 IDisposable接口(interface),并且仅当 Dispose() 非常重要时才使用终结器被调用,即使程序员忘记了它(例如释放共享网络/文件资源等)

关于.net - .Net 中触发垃圾收集的标准,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2671161/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com