检测“泄露”的IDisposable对象

有很多问题要求如何检测IDisposable对象泄漏。 似乎答案是“你不能” 。

我只是检查了最简单的测试用例,FxCop 10.0没有这样做,带有MSVS2010的ReSharper 4没有这样做。

这对我来说似乎不对,比C中的内存泄漏更糟糕(至少我们已经建立了检测工具)。

我在想:是否有可能使用reflection和其他模糊的高级技术,我可以在运行时注入一个检查,在终结器中查看是否已调用Dispose

WinDBG + SOS的魔术技巧怎么样?

即使没有现成的工具,我也想知道这在理论上是否可行(我的C#不是很尖锐)。

想法?

注意这个问题的标题可能会产生误导。 这里真正的问题应该是IDisposable对象是否已正确使用Disposed() 。 由于我认为这是一个错误,因此由GC处理并不重要。

编辑 :解决方案:.NET Memory Profiler完成工作。 我们只需要在程序结束时垃圾邮件几个GC.Collect() ,以使我们的探查器能够正确地获取统计数据。

你搜索不够努力。 有很多.NET内存配置文件可以在程序运行时查看您的程序,并让您知道内存的使用位置(以及泄漏的内容)。

我会检查以下任何一项:

微软的CLR Memory Profiler(免费)
RedGate ANTS Memory Profiler
JetBrain的DotTrace(包括代码分析器)
SciTech .NET内存分析器

更新

SciTech的.NET内存分析器具有一个名为“Dispose Tracker”的function,该function符合OP的要求,即仅在其应用程序中跟踪Dispose调用。

你可以通过向IDisposable对象添加Finalizer来实现。 在终结器中,您可以检查对象是否已被丢弃。 如果尚未处理,您可以断言,或者将某些内容写入日志或其他内容。

  ~Disposable() { #if DEBUG // In debug-builds, make sure that a warning is displayed when the Disposable object hasn't been // disposed by the programmer. if( _disposed == false ) { System.Diagnostics.Debug.Fail ("There is a disposable object which hasn't been disposed before the finalizer call: {0}".FormatString (this.GetType ().Name)); } #endif Dispose (false); } 

您可以将此functionDisposable类 – Disposable – 例如,可以将其用作模板来实现一次性模式。

像这样,例如:

  ///  /// Abstract base class for Disposable types. ///  /// This class makes it easy to correctly implement the Disposable pattern, so if you have a class which should /// be IDisposable, you can inherit from this class and implement the DisposeManagedResources and the /// DisposeUnmanagedResources (if necessary). ///  public abstract class Disposable : IDisposable { private bool _disposed = false; ///  /// Releases the managed and unmanaged resources. ///  public void Dispose() { Dispose (true); GC.SuppressFinalize (this); } ///  /// Releases the unmanaged and managed resources. ///  /// When disposing is true, the managed and unmanaged resources are /// released. /// When disposing is false, only the unmanaged resources are released. [System.Diagnostics.CodeAnalysis.SuppressMessage ("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")] protected void Dispose( bool disposing ) { // We can suppress the CA1063 Message on this method, since we do not want that this method is // virtual. // Users of this class should override DisposeManagedResources and DisposeUnmanagedResources. // By doing so, the Disposable pattern is also implemented correctly. if( _disposed == false ) { if( disposing ) { DisposeManagedResources (); } DisposeUnmanagedResources (); _disposed = true; } } ///  /// Override this method and implement functionality to dispose the /// managed resources. ///  protected abstract void DisposeManagedResources(); ///  /// Override this method if you have to dispose Unmanaged resources. ///  protected virtual void DisposeUnmanagedResources() { } ///  /// Releases unmanaged resources and performs other cleanup operations before the ///  is reclaimed by garbage collection. ///  [System.Diagnostics.CodeAnalysis.SuppressMessage ("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")] ~Disposable() { #if DEBUG // In debug-builds, make sure that a warning is displayed when the Disposable object hasn't been // disposed by the programmer. if( _disposed == false ) { System.Diagnostics.Debug.Fail ("There is a disposable object which hasn't been disposed before the finalizer call: {0}".FormatString (this.GetType ().Name)); } #endif Dispose (false); } } 

虽然@Justin Niessner的推荐有效,但我发现使用完整的剖析器太重了。

我创造了我的家酿解决方案: EyeDisposable 。 它检测程序集以检测何时未调用Dispose