Что это за "объект ручки закрепления []", который я вижу в Jetbrains dotMemory, когда использую List<T>?
Я попытался придумать самый простой код, чтобы воспроизвести то, что я вижу. Полная программа приведена ниже, но я опишу ее здесь. Предположим, у меня есть класс с именем ListData
это просто имеет некоторые свойства. Тогда предположим, что у меня есть MyList
класс, в котором есть член List<ListData> m_list
, предполагать m_list
инициализируется в MyList
конструктор.
В основном методе я просто создаю один из этих MyList
объекты, добавить несколько ListData
к этому, тогда позвольте этому выйти из области видимости. Я делаю снимок в dotMemory после ListData
был добавлен, то я делаю еще один снимок после 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();
}
}
}
шаги:
- Постройте приведенный выше код в релизе.
- В dotMemory выберите для профилирования автономное приложение.
- Перейдите к выпуску exe.
- Выберите опцию, чтобы начать сбор данных о распределении немедленно.
- Нажмите Run.
- Сделайте моментальный снимок и назовите его "раньше". Это до того, как какие-либо ListData были добавлены.
- В приложении введите и добавьте два ListData.
- В dotMemory, сделайте еще один снимок и назовите его "добавлено 2", потому что мы добавили два ListData.
- В приложении введите q, чтобы выйти (MyList выйдет из области видимости). Прежде чем снова ввести Enter, чтобы выйти из приложения, сделайте еще один снимок в dotMemory. Назовите это "вне области".
- В приложении введите Enter, чтобы закрыть приложение.
- В dotMemory сравните "добавленные 2" и "вне области" снимки. Группировать по пространству имен. Вы увидите ListData[], на который я ссылаюсь.
Обратите внимание на то, что MyList и два объекта ListData собирали мусор, а ListData[] - нет. Почему существует ListData[]? Как я могу заставить его собирать мусор?
1 ответ
Почему существует ListData[]? Как я могу заставить его собирать мусор?
Если вы посмотрите на "Creation Stack Trace" внутри dotMemory, вы увидите:
Это показывает вам, что пустой ListData[0]
Экземпляр был создан с помощью статического конструктора List<T>
, Если вы посмотрите на источник, вы увидите это:
static readonly T[] _emptyArray = new T[0];
List<T>
инициализирует пустой массив по умолчанию для оптимизации, чтобы избежать такого распределения при каждом создании нового List<T>
, Это конструктор по умолчанию:
public List()
{
_items = _emptyArray;
}
Только один вы используете List<T>.Add
Будет ли это изменить размер массива.
static
ссылки на членов из "Кучи высокой частоты", которые создаются один раз для каждого AppDomain
в вашем приложении. Закрепленный object[]
вы видите на самом деле место, где все static
экземпляры хранятся.
Поскольку экземпляр static
, он останется в памяти на время жизни вашего приложения.