[英]Detecting “leaked” IDisposable objects
有很多問題要求如何檢測IDisposable對象泄漏。 似乎答案是“你不能” 。
我剛剛用最瑣碎的測試用例檢查過,FxCop 10.0沒有這樣做,帶有MSVS2010的ReSharper 4沒有這樣做。
這對我來說似乎不對,比C中的內存泄漏更糟糕(至少我們已經建立了檢測工具)。
我在想:是否有可能使用反射和其他模糊的高級技術,我可以在運行時注入一個檢查,在終結器中查看是否已調用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”的功能,該功能符合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);
}
您可以將此功能Disposable
類 - Disposable
- 例如,可以將其用作模板來實現例如Disposable模式。
像這樣,例如:
/// <summary>
/// Abstract base class for Disposable types.
/// </summary>
/// <remarks>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).
/// </remarks>
public abstract class Disposable : IDisposable
{
private bool _disposed = false;
/// <summary>
/// Releases the managed and unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose (true);
GC.SuppressFinalize (this);
}
/// <summary>
/// Releases the unmanaged and managed resources.
/// </summary>
/// <param name="disposing">When disposing is true, the managed and unmanaged resources are
/// released.
/// When disposing is false, only the unmanaged resources are released.</param>
[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;
}
}
/// <summary>
/// Override this method and implement functionality to dispose the
/// managed resources.
/// </summary>
protected abstract void DisposeManagedResources();
/// <summary>
/// Override this method if you have to dispose Unmanaged resources.
/// </summary>
protected virtual void DisposeUnmanagedResources()
{
}
/// <summary>
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="Disposable"/> is reclaimed by garbage collection.
/// </summary>
[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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.