代表会造成内存泄漏? GC.TotalMemory(true)似乎表明如此 [英] Can delegates cause a memory leak? GC.TotalMemory(true) seems to indicate so

查看:146
本文介绍了代表会造成内存泄漏? GC.TotalMemory(true)似乎表明如此的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码

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


推荐答案

p>有趣的情况。这是解决方案:

Interesting case. Here is the solution:

组合代表是观察纯粹:看起来代表是不可变的外部。但是,在内部,现有代表正在修改。由于性能原因,在某些条件下,它们共享相同的 _invocationList (优化了一些代理被挂接到同一事件的场景)。不幸的是, simpleCombinedDelegate _invocationList 引用了 bigMgdResDelegate 导致内存保持活着。

Combining delegates is observationally pure: It looks like delegates are immutable to the outside. But internally, existing delegates are being modified. They share, under certain conditions, the same _invocationList for performance reasons (optimizing for the scenario that a few delegates are hooked up to the same event). Unfortunately, the _invocationList for the simpleCombinedDelegate references the bigMgdResDelegate which causes the memory to be kept alive.

这篇关于代表会造成内存泄漏? GC.TotalMemory(true)似乎表明如此的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆