c# - 委托(delegate)会导致内存泄漏吗? GC.TotalMemory(true) 似乎表明如此

标签 c# .net memory-leaks delegates garbage-collection

代码

using System;
internal static class Test
{
    private static void Main()
    {
        try
        {
            Console.WriteLine("{0,10}: Start point", GC.GetTotalMemory(true));
            Action simpleDelegate = SimpleDelegate;
            Console.WriteLine("{0,10}: Simple delegate created", GC.GetTotalMemory(true));
            Action simpleCombinedDelegate = simpleDelegate + simpleDelegate + simpleDelegate;
            Console.WriteLine("{0,10}: Simple combined delegate created", GC.GetTotalMemory(true));
            byte[] bigManagedResource = new byte[100000000];
            Console.WriteLine("{0,10}: Big managed resource created", GC.GetTotalMemory(true));
            Action bigManagedResourceDelegate = bigManagedResource.BigManagedResourceDelegate;
            Console.WriteLine("{0,10}: Big managed resource delegate created", GC.GetTotalMemory(true));
            Action bigCombinedDelegate = simpleCombinedDelegate + bigManagedResourceDelegate;
            Console.WriteLine("{0,10}: Big combined delegate created", GC.GetTotalMemory(true));
            GC.KeepAlive(bigManagedResource);
            bigManagedResource = null;
            GC.KeepAlive(bigManagedResourceDelegate);
            bigManagedResourceDelegate = null;
            GC.KeepAlive(bigCombinedDelegate);
            bigCombinedDelegate = null;
            Console.WriteLine("{0,10}: Big managed resource, big managed resource delegate and big combined delegate removed, but memory not freed", GC.GetTotalMemory(true));
            GC.KeepAlive(simpleCombinedDelegate);
            simpleCombinedDelegate = null;
            Console.WriteLine("{0,10}: Simple combined delegate removed, memory freed, at last", GC.GetTotalMemory(true));
            GC.KeepAlive(simpleDelegate);
            simpleDelegate = null;
            Console.WriteLine("{0,10}: Simple delegate removed", GC.GetTotalMemory(true));
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        Console.ReadKey(true);
    }
    private static void SimpleDelegate() { }
    private static void BigManagedResourceDelegate(this byte[] array) { }
}

输出

GC.TotalMemory(true)
    105776: Start point
    191264: Simple delegate created
    191328: Simple combined delegate created
 100191344: Big managed resource created
 100191780: Big managed resource delegate created
 100191812: Big combined delegate created
 100191780: Big managed resource, big managed resource delegate and big combined delegate removed, but memory not freed
    191668: Simple combined delegate removed, memory freed, at last
    191636: Simple delegate removed

最佳答案

有趣的案例。这是解决方案:

enter image description here

合并委托(delegate)是纯观察:看起来委托(delegate)对外部是不可变的。但是在内部,正在修改现有的委托(delegate)。在某些情况下,它们出于性能原因共享相同的 _invocationList(针对几个委托(delegate)连接到同一事件的场景进行优化)。不幸的是,simpleCombinedDelegate_invocationList 引用了 bigMgdResDelegate,这导致内存保持事件状态。

关于c# - 委托(delegate)会导致内存泄漏吗? GC.TotalMemory(true) 似乎表明如此,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10524107/

相关文章:

C# 客户端通过 SSL 连接到 Java 服务器

c# - 未将对象引用设置为行 if (!string.IsNullOrEmpty(tdcd.Text) && !string.IsNullOrEmpty(tdrcd.Text)) 处的对象实例

.net - 在 .NET 中反转字节顺序

c# - Unity注册抽象类和解析派生类

c - 为传递给函数的数组指针初始化内存时出现段错误

c - 为什么在 pthread_create 后未分离线程时未加入的 pthread 会泄漏资源

exception - 处理 "java.lang.OutOfMemoryError: PermGen space"错误

c# - 表达式树依赖分析器

c# - 如何避免使用Nest .NET 6.x将重复项发布到elasticsearch中?

c# - XmlDocument:空白处理和规范化