gpt4 book ai didi

c# - .NetFramework 4.8 和 .Net 5 之间的垃圾收集行为差异

转载 作者:行者123 更新时间:2023-12-04 12:30:15 24 4
gpt4 key购买 nike

为了在已经经常发生内存泄漏的地方检测潜在的内存泄漏,我使用了如下所示构建的测试。主要思想是拥有一个实例,不再引用它并让垃圾收集器收集它。我不想关注这是否是一项好技术(在我的特定情况下它做得很好),但我想关注以下问题:

下面的代码在 .NetFramework 4.8 上运行良好,但在 .Net 5 上运行不正常。为什么?

[Test]
public void ConceptualMemoryLeakTest()
{
WeakReference weakReference;
{
object myObject = new object();
weakReference = new WeakReference(myObject);
myObject = null;
Assert.Null(myObject);
}
Assert.True(weakReference.IsAlive); // instance not collected by GC
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
GC.Collect();
Assert.False(weakReference.IsAlive); // instance collected by GC
}

您可以看到主要思想是使用 WeakReference 并使用 IsAlive 来确定实例是否被 GC 删除。新 CLR(源自 dotnet core 的规则)中的规则是如何变化的?我知道这里所做的并不依赖于指定的内容。相反,我只是利用我在 NetFramework 4.8 中看到的 CLR 行为。

您是否知道如何再次获得同样适用于 .Net 5 的类似内容?

最佳答案

原因可能是tiered compilation .简而言之,分层编译将(对于某些条件下的某些方法)首先编译方法的粗略、低优化版本,然后在必要时准备更好的优化版本。这在 .NET 5(和 .NET Core 3+)中默认启用,但在 .NET 4.8 中不可用。

在你的情况下,结果是你的方法是用提到的“快速”编译编译的,并且没有优化到足以让你的代码按预期工作(即 myObject 变量的生命周期延长到方法结束)。即使您在启用优化且未附加任何调试器的情况下在 Release模式下进行编译,情况也是如此。

您可以 disable通过添加分层编译:

<TieredCompilation>false</TieredCompilation>

给一些<PropertyGroup>在 .NET 5 项目的 csproj 文件中,然后您将观察到与 .NET 4.8 情况下相同的行为。

另一种选择(除了将变量移动到另一个方法并从中返回 WeakReference 之外)是使用:

[MethodImpl(MethodImplOptions.AggressiveOptimization)]

ConceptualMemoryLeakTest 上的属性方法。

关于c# - .NetFramework 4.8 和 .Net 5 之间的垃圾收集行为差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69616548/

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