如何在C#/ .NET中创建内存泄漏

Den*_*dic 5 .net c# memory-leaks

可能重复:
托管代码中是否可能存在内存泄漏?(特别是C#3.0)
C#中的内存泄漏

昨天有一个类似的问题,但是对于Java,所以我很感兴趣 - 在C#/ .NET中创建内存泄漏需要什么(不使用不安全的)?

Mar*_*ell 12

静态事件; 最后,因为他们永远不会超出范围.

static event EventHandler Evil;

for(int i = 0 ; i < 1000000 ; i++)
    Evil += delegate {};
Run Code Online (Sandbox Code Playgroud)

匿名方法在这里只是一个很好的方法,但很好,因为它们也是取消订阅的猪,除非你将副本带入变量/字段并订阅.

从技术上讲,这实际上并没有"泄露",因为您仍然可以通过它访问它们Evil.GetInvocationList()- 但是,当与常规对象一起使用时,这可能会导致意外的对象生命周期,即

MyHeavyObject obj = ...
...
SomeType.SomeStaticEvent += obj.SomeMethod;
Run Code Online (Sandbox Code Playgroud)

现在obj生命中的对象永远存在.这足以满足感知泄漏的 IMO,并且"我的应用程序死于可怕的死亡"对我来说已经足够了; p

  • 好吧,我认为这真的只是沸腾到'什么是内存泄漏'的辩论;-).我可以看到@Marc和@Ed都在制作这两点.我想我对于我认为真正的内存泄漏更加挑剔.我仍然相信你所描述的情况不是内存泄漏,而是一种导致意外物体生命时间的方法.当然,两者都具有相同的终极效果. (2认同)

Ed *_* S. 5

当一个对象订阅一个事件时,暴露该事件的对象会维护对该订阅者的引用(实际上,该事件是MultiCastDelegate原始的,但它会继续).如果最后一次引用(除了由其维护的引用)超出范围,此引用将阻止订户进行GC event.

另外两个答案完全落后并且不正确.这在一个简单的例子中显示有点棘手,通常在大型项目中看到,但只记得订阅者的引用由MultiCastDelegate(event)维护,你应该能够思考它.

编辑:正如Marc在他的回复中提到的,你可以在技术上通过该GetInvocationList()方法获得对"泄露"对象的引用,但是你的代码不太可能使用它,并且当你崩溃时无关紧要OutOfMemoryExcetion.