C# 什么策略和工具对查找.NET中的内存泄漏有用? 我写C++有10年了。我遇到了内存问题,但只要付出合理的努力就可以解决

C# 什么策略和工具对查找.NET中的内存泄漏有用? 我写C++有10年了。我遇到了内存问题,但只要付出合理的努力就可以解决,c#,.net,memory-management,memory-leaks,C#,.net,Memory Management,Memory Leaks,在过去的几年里,我一直在写C。我发现我仍然有很多记忆问题。由于不确定性,它们很难诊断和修复,因为C#哲理是,当你非常确定的时候,你不应该担心这些事情 我发现的一个特殊问题是,我必须显式地处理和清理代码中的所有内容。如果我不这样做,那么内存分析器就没有真正的帮助,因为到处都是垃圾,你无法在它们试图显示给你的所有数据中找到漏洞。我不知道我是否有错误的想法,或者我的工具不是最好的 什么样的策略和工具对解决.NET中的内存泄漏有用?当我怀疑内存泄漏时,我会使用Scitech的 到目前为止,我发现它非常可

在过去的几年里,我一直在写C。我发现我仍然有很多记忆问题。由于不确定性,它们很难诊断和修复,因为C#哲理是,当你非常确定的时候,你不应该担心这些事情

我发现的一个特殊问题是,我必须显式地处理和清理代码中的所有内容。如果我不这样做,那么内存分析器就没有真正的帮助,因为到处都是垃圾,你无法在它们试图显示给你的所有数据中找到漏洞。我不知道我是否有错误的想法,或者我的工具不是最好的

什么样的策略和工具对解决.NET中的内存泄漏有用?

当我怀疑内存泄漏时,我会使用Scitech的

到目前为止,我发现它非常可靠和强大。至少有一次它救了我的命


GC在.NET IMO中工作得很好,但就像任何其他语言或平台一样,如果您编写的代码不好,就会发生不好的事情。

在编写托管代码时,您仍然需要担心内存问题,除非您的应用程序微不足道。我建议两件事:首先,通过C#阅读CLR,因为它将帮助您理解.NET中的内存管理。其次,学习使用CLRProfiler(微软)等工具。这可以让您了解导致内存泄漏的原因(例如,您可以查看大型对象堆碎片)

我们在项目中使用了Red Gate软件。它适用于所有基于.NET语言的应用程序

我们发现.NET垃圾收集器在清理内存中的对象时非常“安全”(应该如此)。它会把物体留在周围,只是因为将来某个时候我们可能会使用它。这意味着我们需要更加小心地考虑我们在内存中膨胀的对象的数量。最后,我们将所有数据对象转换为“按需充气”(就在请求字段之前),以减少内存开销并提高性能

编辑:下面是对我所说的“按需充气”的进一步解释。在数据库的对象模型中,我们使用父对象的属性来公开子对象。例如,如果我们有一些记录引用了其他一些“详细信息”或“查找”记录,我们会这样构造它:

class ParentObject
   Private mRelatedObject as New CRelatedObject
   public Readonly property RelatedObject() as CRelatedObject
      get
         mRelatedObject.getWithID(RelatedObjectID)
         return mRelatedObject
      end get
   end property
End class
我们发现,当内存中有大量记录时,上述系统会产生一些实际内存和性能问题。因此,我们切换到一个系统,在这个系统中,对象只有在被请求时才会膨胀,而数据库调用只有在必要时才会进行:

class ParentObject
   Private mRelatedObject as CRelatedObject
   Public ReadOnly Property RelatedObject() as CRelatedObject
      Get
         If mRelatedObject is Nothing
            mRelatedObject = New CRelatedObject
         End If
         If mRelatedObject.isEmptyObject
            mRelatedObject.getWithID(RelatedObjectID)
         End If
         return mRelatedObject
      end get
   end Property
end class

事实证明,这种方法效率更高,因为在需要对象之前,对象一直处于内存之外(Get方法被访问)。它在限制数据库命中率方面提供了极大的性能提升,并极大地增加了内存空间。

最好记住的是跟踪对对象的引用。最终很容易挂起对您不再关心的对象的引用。 如果你不打算再使用某些东西,就把它扔掉


习惯于使用具有滑动过期的缓存提供程序,这样,如果某个对象在所需的时间窗口内未被引用,它将被取消引用并清理。但是如果它被大量访问,它会说在内存中。

最好的工具之一是使用,并使用adplus对进程进行内存转储,然后使用windbgsos插件来分析进程内存、线程和调用堆栈

您也可以使用此方法来识别服务器上的问题,在安装工具后,共享目录,然后使用(net use)从服务器连接到共享,并对进程进行崩溃或挂起转储


然后分析脱机。

< P>如果您观察到的泄漏是由于失控的高速缓存实现,这是一个场景,您可能需要考虑使用WeakReference。这有助于确保在必要时释放内存


但是,IMPO最好考虑一个定制的解决方案——只有你真正知道需要多长时间来保持对象的周围,所以为你的情况设计合适的内务代码通常是最好的方法。

< P>只是为了忘记处理问题,试试。以下是要点:

    public void Dispose ()
    {
        // Dispose logic here ...

        // It's a bad error if someone forgets to call Dispose,
        // so in Debug builds, we put a finalizer in to detect
        // the error. If Dispose is called, we suppress the
        // finalizer.
#if DEBUG
        GC.SuppressFinalize(this);
#endif
    }

#if DEBUG
    ~TimedLock()
    {
        // If this finalizer runs, someone somewhere failed to
        // call Dispose, which means we've failed to leave
        // a monitor!
        System.Diagnostics.Debug.Fail("Undisposed lock");
    }
#endif

您正在使用非托管代码吗?根据微软的说法,如果你不使用非托管代码,传统意义上的内存泄漏是不可能的

但是,应用程序使用的内存可能不会被释放,因此应用程序的内存分配可能会在应用程序的整个生命周期中增长

.NET中可能会发生内存泄漏 当您使用 非托管代码作为 应用这种非托管代码可以 泄漏内存和.NET Framework 运行时无法解决该问题

此外,项目可能仅限于 似乎有内存泄漏。这 如果许多大的 对象(例如DataTable对象) 声明,然后添加到 集合(例如数据集)。这个 这些对象拥有的资源可能 永远不要释放资源 在整个过程中都是活着的 节目。这似乎是一个错误 泄漏,但实际上它只是一个 记忆方式的症状 在程序中被分配

对于处理此类问题,您可以实现。如果您想了解一些处理内存管理的策略,我建议您搜索IDisposable、XNA和内存管理,因为游戏开发人员需要有更可预测的垃圾收集,因此必须强制GC完成它的工作

一个常见的错误是t