Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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# 这是什么;钉住控制柄对象[]”;当我使用列表时在Jetbrains dotMemory中看到的<;T>;?_C#_.net_Memory Management - Fatal编程技术网

C# 这是什么;钉住控制柄对象[]”;当我使用列表时在Jetbrains dotMemory中看到的<;T>;?

C# 这是什么;钉住控制柄对象[]”;当我使用列表时在Jetbrains dotMemory中看到的<;T>;?,c#,.net,memory-management,C#,.net,Memory Management,我试图用最简单的代码来重现我所看到的。下面是完整的程序,但我将在这里描述它。假设我有一个名为ListData的类,它只有一些属性。然后假设我有一个MyList类,它有一个成员List m\u List。假设m_list在MyList构造函数中初始化 在main方法中,我只需创建一个MyList对象,向其中添加一些ListData,然后让它超出范围。添加ListData后,我在dotMemory中拍摄快照,然后在MyList对象超出范围后拍摄另一个快照 在dotMemory中,我可以看到MyLis

我试图用最简单的代码来重现我所看到的。下面是完整的程序,但我将在这里描述它。假设我有一个名为
ListData
的类,它只有一些属性。然后假设我有一个
MyList
类,它有一个成员
List m\u List
。假设
m_list
MyList
构造函数中初始化

在main方法中,我只需创建一个
MyList
对象,向其中添加一些
ListData
,然后让它超出范围。添加
ListData
后,我在dotMemory中拍摄快照,然后在
MyList
对象超出范围后拍摄另一个快照

在dotMemory中,我可以看到
MyList
对象已按预期回收。我还看到,我创建的两个
ListData
对象也按照预期得到了回收

我不明白的是,为什么有一个
ListData[]
幸存了下来? 以下是此项目的屏幕截图:

我在最新的快照上为
ListData[]
打开幸存的对象,然后查看密钥保留路径,这就是我看到的

我不熟悉.NET内存管理,我创建了这个示例应用程序来帮助我探索它。我下载了JetBrains dotMemory 4.3版的试用版。我正在使用Visual Studio 2013 Professional。我必须学习内存管理,这样才能解决工作中的内存问题

这里是完整的程序,可以用来重现这一点。这只是一个快速而肮脏的应用程序,但如果你对它进行分析,它会得到我想要的东西

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{

    class ListData
    {
        public ListData(string name, int n) { Name = name; Num = n; }
        public string Name { get; private set; }
        public int Num { get; private set; }
    }

    class MyList
    {

        public MyList()
        {
            m = new List<ListData>();
        }

        public void AddString(ListData d)
        {
            m.Add(d);
        }

        private List<ListData> m;

    }


    class Program
    {
        static void Main(string[] args)
        {
            {
                MyList l = new MyList();
                bool bRunning = true;
                while (bRunning)
                {
                    Console.WriteLine("a or q");
                    string input = Console.ReadLine();
                    switch (input)
                    {
                        case "a":
                            {
                                Console.WriteLine("Name: ");
                                string strName = Console.ReadLine();
                                Console.WriteLine("Num: ");
                                string strNum = Console.ReadLine();
                                l.AddString(new ListData(strName, Convert.ToInt32(strNum)));
                                break;
                            }
                        case "q":
                            {
                                bRunning = false;
                                break;
                            }
                    }
                }
            }

            Console.WriteLine("good bye");
            Console.ReadLine();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间控制台应用程序1
{
类列表数据
{
公共ListData(字符串名,int n){name=name;Num=n;}
公共字符串名称{get;private set;}
public int Num{get;private set;}
}
类MyList
{
公共MyList()
{
m=新列表();
}
公共void AddString(ListData d)
{
m、 加(d);
}
私人名单m;
}
班级计划
{
静态void Main(字符串[]参数)
{
{
MyList l=新的MyList();
布尔·布伦宁=真;
当(布伦宁)
{
控制台写入线(“a或q”);
字符串输入=Console.ReadLine();
开关(输入)
{
案例“a”:
{
Console.WriteLine(“名称:”);
字符串strName=Console.ReadLine();
控制台。WriteLine(“Num:”);
字符串strNum=Console.ReadLine();
l、 AddString(新列表数据(strName,Convert.ToInt32(strNum));
打破
}
案例“q”:
{
布鲁宁=假;
打破
}
}
}
}
Console.WriteLine(“再见”);
Console.ReadLine();
}
}
}
步骤:

  • 在发行版中构建上述代码
  • 在dotMemory中,选择以评测 独立应用程序
  • 浏览到发布exe
  • 选择该选项以立即开始收集分配数据
  • 单击运行
  • 立即拍摄快照并将其命名为“before”。这是在任何之前 已添加ListData
  • 在应用程序中,键入a并添加两个ListData
  • 在dotMemory中,拍摄另一个快照并将其命名为“added 2”,因为我们 添加了两个ListData
  • 在应用程序中,键入q退出(MyList将超出范围)。在再次键入Enter退出应用程序之前,请在dotMemory中拍摄另一个快照。将其命名为“超出范围”
  • 在应用程序中,键入Enter关闭应用程序
  • 在dotMemory中,比较“添加的2”和“超出范围” 快照。按名称空间分组。您将看到我所指的ListData[]
  • 请注意,MyList和两个ListData对象确实被垃圾回收,但ListData[]没有。为什么有一个ListData[]挂在周围?我怎样才能把垃圾收集起来

    为什么有一个ListData[]挂在周围?我怎样才能让它变得更好 垃圾收集

    如果查看dotMemory中的“创建堆栈跟踪”,您将看到:

    这表明空的
    ListData[0]
    实例是通过
    List
    的静态构造函数创建的,您将看到:

    static readonly T[]  _emptyArray = new T[0];    
    
    List
    初始化一个默认的空数组,以便在每次创建一个新的
    List
    时避免这样的分配。这是默认构造函数:

    public List() 
    {
        _items = _emptyArray;
    }
    
    只有一个您使用的
    List.Add
    ,它将调整数组的大小

    static
    成员从引用,在应用程序中为每个
    AppDomain
    创建一次。您看到的固定的
    对象[]
    实际上是存储所有
    静态
    实例的位置


    由于实例是静态的,它将在应用程序的生命周期内一直保留在内存中。

    Yuval,感谢您的回复。我正在查看您的答案,以便理解,如果我有问题,我会让您知道。为了确保我理解正确,请允许我用自己的话解释,如果我错了,请纠正我。我看到的是静态的空射线被抛在了后面。由于_emptyArray是静态的,它将始终是空数组的根,因此它永远不会被垃圾收集