检测“泄露”的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
。