了解C#中的悬空引用

时间:2014-10-13 16:53:19

标签: c# memory-management garbage-collection

我正在努力教育自己如何在C#这样的垃圾收集语言中发生泄漏或悬空引用。我在网上发现了一个人为的例子,我修改并观察(通过任务管理器),以便在每次击键时保持“漏水”。

来源:

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    public class Something
    {
        int[] things;

        public Something() {
            things = new int[10000000];
            Random rnd = new Random();
            for (int i = 0; i < things.Length; ++i) {
                things[i] = rnd.Next();
            }
        }
    }

    static public class SomethingFactory
    {
        public static Something CreateSomething() {
            Something something = new Something();
            return something;
        }
    }

    class Program
    {
        static void Main(string[] args) {

            while (true) {
                Console.ReadKey();

                Console.WriteLine("Creating...");
                Something s = SomethingFactory.CreateSomething();
            }

        }
    }
}

悬空参考为什么会出现?乍一看,似乎Something swhile (true)的范围内被实例化,并且在块结束之后,不应该存在对该项的其他引用。然而,随着每一次击键,我看到我的应用程序的内存使用量增加了约40mb,似乎永远不会下降。

1 个答案:

答案 0 :(得分:1)

你没有做任何与众不同的事情。报告中报告的大量内存可以在样本中由GC回收。但是,请记住,当您在任务管理器中观察内存时,您正在查看进程内存。在托管应用程序中,CLR代表您的应用程序充当内存管理器。它在进程级别分配和释放内存。

工作方式是它分配内存块来存储托管堆上的对象。当对象数量下降时,这些卡盘最终会再次释放到OS。要记住的是CLR试图巧妙地做到这一点,因此每次托管堆更改时它都不会分配和释放。因此,通过查看进程级内存使用情况很难理解如何使用托管内存。

你看到的很可能就是内存被分配而不是被释放,因为CLR还没有任何理由来释放这些chucks。