我试图想出最简单的代码来重现我所看到的内容。完整的程序如下,但我将在这里描述它。假设我有一个名为ListData
它只是有一些属性。那么假设我有一个MyList
有成员的类List<ListData> m_list
。认为m_list
被初始化在MyList
构造函数。
在主要方法中我只是创建其中之一MyList
对象,添加一些ListData
到它,然后让它超出范围。我在 dotMemory 后拍摄快照ListData
已添加,然后我在添加后拍摄另一张快照MyList
对象超出范围。
在 dotMemory 中我可以看到MyList
对象已按预期被回收。我也看到了两个ListData
我创建的对象也按预期被回收。
What I do not understand is why is there a ListData[]
that survived?
Here is a screen shot of this:
我在最新快照上打开幸存的对象ListData[]
然后我查看关键保留路径,这就是我看到的。
我是 .NET 内存管理的新手,我创建了这个示例应用程序来帮助我探索它。我下载了 JetBrains dotMemory 4.3 版的试用版。我使用的是 Visual Studio 2013 专业版。我必须学习内存管理,这样我才能解决工作中遇到的内存问题。
这是可用于重现此内容的完整程序。这只是一个快速而肮脏的应用程序,但如果你分析它,它就会得到我要问的东西。
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();
}
}
}
Steps:
- 在发布中构建上述代码。
- 在 dotMemory 中,选择分析
独立应用程序。
- 浏览到发行版 exe。
- 选择立即开始收集分配数据的选项。
- 单击运行。
- 立即拍摄快照并将其命名为“before”。这是在任何之前
添加了列表数据。
- 在应用程序中,键入 a 并添加两个 ListData。
- 在 dotMemory 中,拍摄另一个快照并将其命名为“added 2”,因为我们
添加了两个ListData。
- 在应用程序中,输入 q 退出(MyList 将超出范围)。在再次输入 Enter 退出应用程序之前,请在 dotMemory 中拍摄另一个快照。将其命名为“超出范围”。
- 在应用程序中,输入 Enter 以关闭应用程序。
- 在dotMemory中,比较“添加的2”和“超出范围”
快照。按名称空间分组。您将看到我所指的 ListData[]。
请注意,MyList 和两个 ListData 对象确实得到了垃圾回收,但 ListData[] 没有。为什么有一个 ListData[] 挂在周围?我怎样才能让它被垃圾收集?