下面的代码有一个内存泄漏。
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
AssemblyResolveMemoryTest assemblyResolveMemoryTest = new AssemblyResolveMemoryTest();
}
}
}
class AssemblyResolveMemoryTest
{
private byte[] _allocateMemory;
public AssemblyResolveMemoryTest()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
//memory is not released anymore
_allocateMemory = new byte[300000000];
}
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return null;
}
}似乎是AssemblyResolve事件导致了内存泄漏。
这是什么原因呢?在这种情况下,我需要显式删除eventhandler吗?如果是,在哪里删除这个晚上的处理器是正确的?实现IDisposable还是使用Try/Finally?
发布于 2012-02-23 17:19:18
是的,该事件将导致内存泄漏。这是因为AppDomain.CurrentDomain.AssemblyResolve是静态的,所以直到程序结束它的生命才会结束。因此,它必须保留对已注册(+=)到它的所有事件处理程序的引用,以便当发生导致处理程序被调用的事件时,这些事件处理程序仍保留在内存中。
我建议您在AssemblyResolveMemoryTest类中实现IDisposable,并将其用于-=事件。
然后在for循环中添加一条using语句,该语句将导致dispose被调用。
for (int i = 0; i < 10; i++)
{
using( AssemblyResolveMemoryTest assemblyResolveMemoryTest = new AssemblyResolveMemoryTest() )
{
}
}您可以将assemblyResolveMemoryTest实例存储在一个列表中,并编写第二个循环,在您的程序存在之前循环调用Dispose。不过这并没有多大意义,因为当你的程序存在时,所有的东西都会被处理掉,“泄漏的内存”也会被释放。
因此,在现实中,如果您确实希望这些事件处理程序保留并在程序的生命周期中使用,那么这实际上不是内存泄漏,而是您的程序需要按您希望的方式运行的内存使用量。
我猜buffer不是你在真正的程序中拥有的东西,你只是用它来演示问题。也许,如果您的内存被生产代码中的一个真正的assemblyResolveMemoryTest等价对象引用,您可以尝试重新构造您的程序,以便AssemblyResolve的事件处理程序不是持有与事件处理无关的其他内存的对象的一部分。
您可以使用静态方法作为事件处理程序,这样类的任何成员对象都不会停留在内存中,因为您实际上一开始就不需要创建类的实例。
https://stackoverflow.com/questions/9409910
复制相似问题