Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “检测”;“泄露”;可识别对象_C#_.net_Idisposable_Memory Leaks - Fatal编程技术网

C# “检测”;“泄露”;可识别对象

C# “检测”;“泄露”;可识别对象,c#,.net,idisposable,memory-leaks,C#,.net,Idisposable,Memory Leaks,有很多问题,所以问如何检测IDisposable对象泄漏。答案似乎是 我刚刚用最简单的测试用例检查了一下,FxCop 10.0没有做到,MSVS2010的ReSharper 4没有做到 在我看来,这似乎是错误的,比C语言中的内存泄漏更糟糕(至少我们已经建立了检测工具) 我在想:使用反射和其他模糊的高级技术,我是否可以在运行时在终结器中注入一个检查,以查看是否调用了Dispose WinDBG+SOS的魔术怎么样 即使没有现成的工具,我也想知道这在理论上是否可行(我的C#不是很锋利) 想法 注意这

有很多问题,所以问如何检测IDisposable对象泄漏。答案似乎是

我刚刚用最简单的测试用例检查了一下,FxCop 10.0没有做到,MSVS2010的ReSharper 4没有做到

在我看来,这似乎是错误的,比C语言中的内存泄漏更糟糕(至少我们已经建立了检测工具)

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

WinDBG+SOS的魔术怎么样

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

想法

注意这个问题的标题可能有误导性。这里真正的问题应该是
IDisposable
对象是否已正确地
Disposed()
。被GC处置并不重要,因为我认为这是一个错误


编辑:解决方案:.NET内存探查器执行此任务。我们只需要在程序结束时发送几个
GC.Collect()
,以使我们的探查器能够正确地获取统计数据。

您搜索得不够努力。有很多.NET内存分析器可以在程序运行时查看程序,让您知道在哪里/如何使用内存(以及内存泄漏的原因)

我会检查以下任何一项:




更新


SciTech的.NET内存探查器有一个名为“Dispose Tracker”的功能,适合OP只跟踪其应用程序中的Dispose调用的请求。

您可以通过向IDisposable对象添加终结器来完成此操作。 在终结器中,可以检查对象是否已被释放。如果它还没有被处理,你可以断言它,或者写一些东西到日志中,或者别的什么

 ~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);
 }
例如,您可以将此功能分解为一个基类-
一次性的
,该基类可以用作实现该模式的模板

比如说:

    /// <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);
        }
    }
//
///一次性类型的抽象基类。
/// 
///这个类使正确实现一次性模式变得容易,因此如果您有一个类
///如果可以IDisposable,则可以从此类继承并实现DisposeManagedResources和
///处置托管资源(如有必要)。
/// 
公共抽象类:IDisposable
{
private bool_disposed=false;
/// 
///释放托管和非托管资源。
/// 
公共空间处置()
{
处置(真实);
GC.1(本);
}
/// 
///释放非托管和托管资源。
/// 
///如果disposing为true,则托管资源和非托管资源为
///释放。
///如果disposing为false,则仅释放非托管资源。
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Design”,“CA1063:ImplementIDisposableCorrectly”)]
受保护的无效处置(bool处置)
{
//我们可以抑制此方法上的CA1063消息,因为我们不希望此方法无效
//虚拟的。
//此类的用户应重写DisposeManagedResources和DisposeManagedResources。
//通过这样做,一次性模式也得到了正确的实现。
如果(_=false)
{
如果(处置)
{
DisposeManagedResources();
}
DisposeUnmanagedResources();
_这是真的;
}
}
/// 
///重写此方法并实现功能以处置
///管理资源。
/// 
受保护的抽象空处理数据源();
/// 
///如果必须处置非托管资源,请重写此方法。
/// 
受保护的虚拟void DisposeUnmanagedResources()
{
}
/// 
///释放非托管资源并在
///通过垃圾收集回收。
/// 
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Design”,“CA1063:ImplementIDisposableCorrectly”)]
~一次性的()
{
#如果调试
//在调试生成中,确保在未安装一次性对象时显示警告
//由程序员处理。
如果(_=false)
{
System.Diagnostics.Debug.Fail(“有一个一次性对象在终结器调用之前未被释放:{0}”).FormatString(this.GetType().Name));
}
#恩迪夫
处置(虚假);
}
}

虽然@Justin Niessner的建议有效,但我发现使用全面的分析器太麻烦了


我创建了我的自制解决方案:。当
Dispose
未被调用时,它会指示程序集进行检测。

这是检测
Dispose
还是仅检测内存?如果我的
IDisposable
对象只有
Console.WriteLine(“baz”)(我知道这是个糟糕的例子,但你明白了),我想确保它不是被GC调用的?@kizzx2-它会检测到所有东西,但从那里你可以缩小范围,找到你要找的东西。我对RedGate的蚂蚁记忆分析器有着最好的体验。@Uwe Keim:RedGate的蚂蚁记忆分析器能跟踪问题的实际问题吗?(这是列表中唯一一个需要发送电子邮件进行评估的功能——现在懒得这么做)