Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.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#_Memory Leaks - Fatal编程技术网

C# 内存泄漏#

C# 内存泄漏#,c#,memory-leaks,C#,Memory Leaks,我试图更好地理解内存泄漏的概念。谁能指出一些有用的信息来帮助我更好地理解内存泄漏的确切含义,以及如何在代码中找到它们。当您的程序动态分配在使用完内存后未正确释放的内存时,就会发生内存泄漏。如果你有一个程序持续这样做,你的漏洞会越来越大,很快你的程序就占用了你所有的RAM。一个非常好的解读是 通常,内存泄漏或任何资源泄漏是指程序分配内存(或任何其他资源),然后在完成分配后忽略释放内存。在本机应用程序中,内存泄漏是最常见的资源泄漏,当资源引用(指向已分配块的指针)超出范围并被销毁,但已分配资源(内存

我试图更好地理解内存泄漏的概念。谁能指出一些有用的信息来帮助我更好地理解内存泄漏的确切含义,以及如何在代码中找到它们。

当您的程序动态分配在使用完内存后未正确释放的内存时,就会发生内存泄漏。如果你有一个程序持续这样做,你的漏洞会越来越大,很快你的程序就占用了你所有的RAM。

一个非常好的解读是

通常,内存泄漏或任何资源泄漏是指程序分配内存(或任何其他资源),然后在完成分配后忽略释放内存。在本机应用程序中,内存泄漏是最常见的资源泄漏,当资源引用(指向已分配块的指针)超出范围并被销毁,但已分配资源(内存块)未被销毁时,可能会发生内存泄漏。在这种情况下,资源(内存)泄漏是因为程序失去了释放它的能力,即使它想释放,因为它不再记得资源的位置(块的地址)

在托管应用程序中,内存泄漏有点棘手。由于运行时可以自动跟踪对资源的引用,因此它还可以理解应用程序的任何活动部分何时不再引用资源(对象)(在任何线程上都没有从堆栈帧到该资源的引用链)因此,运行时可以理解何时可以安全地收集应用程序不再引用的对象。因此,在托管世界中,当您认为应用程序不再引用某个对象(因此运行时可以收集该对象)时,就会发生“泄漏”,但实际上,通过某些引用链,您确实有对该对象的引用,因此无法收集该对象


我强烈推荐上面链接的Raymond Chen的文章,非常有启发性。

传统的内存泄漏发生在分配内存时,然后不知何故“忘记”返回或取消分配内存。在旧的C++代码中,这意味着调用<代码>新< /代码>,而没有对应的<代码>删除< /代码>。在C语言中,它意味着调用
alloc()
/
malloc()
,但没有相应的
free()

在.Net中,您不会出现传统意义上的内存泄漏,因为您不应该自己释放内存。没有等效于您需要使用的
free()
delete
。即使IDisposable和finalizer也与内存无关。相反,您依赖垃圾收集器(GC)为您释放内存

然而,这并不意味着你永远不会忘记记忆。有几种方法可能会意外地保留引用,从而阻止垃圾收集器执行其工作。其中包括全局变量(特别是列表、字典和其他可能用于“缓存”对象的集合类型)、挂起对象引用的事件处理程序、递归历史引用和大型对象堆


这里还需要注意的是,在.Net中内存使用量不断增加的模式并不一定意味着你的应用程序正在泄漏内存。在总体内存压力较低的情况下,垃圾收集器可能会选择不收集来节省时间,或者只在进程的现有地址空间内收集而不将内存返回操作系统。

存在多种内存泄漏,但一般来说,这个术语指的是某种不再使用但仍占用内存的资源。如果您有很多这样的应用程序,那么您的应用程序会占用大量内存,最终会耗尽内存

在C#中,以下是一些常见的内存泄漏:

  • 不删除事件侦听器。使用引用外部对象的匿名方法或lambda表达式创建的任何事件侦听器都将使这些对象保持活动状态。记住在不再使用事件侦听器时删除它们
  • 保持数据库连接或结果集在未使用时处于打开状态。记住对所有
    IDisposable
    对象调用
    Dispose()
  • 使用p/Invoke调用C函数,该函数分配您永远不会释放的内存
应将“内存泄漏”定义为“当您认为不应该使用它时使用的内存”,以应用于垃圾收集语言/运行时(如C#/Java)


传统上,“内存泄漏”定义为未正确释放的内存(参见其他答案中的wikipedia链接),这通常不会发生在垃圾收集环境中。请注意,由于运行时的问题,即使是垃圾收集的语言也会泄漏内存-即,即使JavaScript是垃圾收集的语言,Internet Explorer的JavaScript运行时也很容易泄漏大量JavaScript对象。

当内存分配给应用程序时,应用程序有义务将该内存释放回操作系统,以便其他应用程序可以重用它。当应用程序不释放内存,从而阻止重新分配内存时,就会发生内存泄漏

对于托管代码,垃圾收集器跟踪对应用程序创建的对象的引用。对于大多数情况,CLR将代表正在运行的进程以透明和合理的方式处理内存分配和释放。然而,NET开发人员仍然需要考虑资源管理,因为尽管垃圾收集器的工作仍存在内存泄漏的情况。

考虑以下代码:

Widget Widget=newwidget()

上面的代码行创建了小部件类的一个新实例,小部件字段被分配了一个对该对象的引用。GC跟踪与每个对象关联的引用,并释放没有强引用的对象的内存

值得一提的是
public void ManagedObject : IDisposable
{
    //A handle to some native resource.
    int* handle;

    public ManagedObject()
    {
        //AllocateHandle is a native method called via P/Invoke.
        handle = AllocateHandle();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            //deal with managed resources here
            FreeHandle(handle);
        }
    }

    ~ManagedType()
    {
        Dispose(false);
    }
}