Próbowałem wymyślić najprostszy kod, aby odtworzyć to, co widzę. Pełny program znajduje się poniżej, ale opiszę to tutaj. Załóżmy, że mam klasę o nazwie ListData
, która ma tylko niektóre właściwości. Załóżmy, że mam klasę MyList
, która ma członka List<ListData> m_list
. Załóżmy, że m_list
zostanie zainicjowany w konstruktorze MyList
.Co to jest "obiekt uchwytów do przypinania []", który widzę w pamięci dot-Speory Jetbrains, gdy używam Listy <T>?
W głównej metodzie po prostu utworzę jeden z tych obiektów MyList
, dodam do niego kilka ListData
, a następnie pozwól mu wyjść poza zakres. Biorę migawkę w dotMemory po dodaniu ListData
, a następnie robię kolejną migawkę po tym, jak obiekt MyList
wychodzi poza zakres.
W dotMemory widzę, że obiekt MyList
został odzyskany zgodnie z oczekiwaniami. Widzę również, że dwa utworzone obiekty ListData
również zostały odzyskane zgodnie z oczekiwaniami.
Czego nie rozumiem, dlaczego przetrwało ListData[]
? Oto zrzut ekranu z tego:
otworzę przetrwały obiekty na najnowszej migawki do ListData[]
potem zobaczyć Kluczowe retencji ścieżek, jest to, co widzę.
Jestem nowy w zarządzaniu pamięcią .NET i ja stworzyliśmy przykładową aplikację, aby pomóc mi go zbadać. Pobrałem wersję próbną JetBrains dotMemory w wersji 4.3. Korzystam z programu Visual Studio 2013 Professional. Muszę nauczyć się zarządzania pamięcią, aby naprawić problemy z pamięcią, które mamy w pracy.
Oto pełny program, który może zostać użyty do odtworzenia tego. Jest to po prostu szybka i brudna aplikacja, ale dostanie to, o co pytam, jeśli to zrobisz.
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();
}
}
}
Kroki:
- Budowa Powyższy kod uwalnianie.
- W dotMemory wybierz profil autonomicznej aplikacji .
- Przejdź do wydania exe.
- Wybierz opcję natychmiastowego rozpoczęcia zbierania danych o przydziałach.
- Kliknij Uruchom.
- Zrób natychmiast migawkę i nadaj jej nazwę "przed". To jest przed dodaniem jakichkolwiek listData .
- W aplikacji wpisz a i dodaj dwie listy danych.
- W dotMemory, zrób kolejną migawkę i nadaj jej nazwę "added 2", ponieważ my dodaliśmy dwie listy danych.
- W aplikacji wpisz q, aby zakończyć (lista MyList zniknie z zakresu). Przed wpisaniem Enter ponownie, aby wyjść z aplikacji, zrób kolejną migawkę w dotMemory. Nazwij go "poza zakresem".
- W aplikacji wpisz Enter, aby zamknąć aplikację.
- W dotMemory porównaj migawki "dodano 2" i "poza zakresem" . Grupuj według przestrzeni nazw. Zobaczysz ListData [], które mam na myśli.
Zauważ, że obiekty MyList i dwa obiekty ListData zostały zbuforowane, ale ListData [] nie. Dlaczego kręci się ListData []? Jak mogę sprawić, że zostaną zebrane śmieci?
Yuval, dziękuję za odpowiedź. Rozglądam się nad twoją odpowiedzią, aby zrozumieć, a dam ci znać, jeśli mam pytania. – cchampion
@cchampion Zapraszamy. –
Ok, aby upewnić się, że rozumiem poprawnie, pozwól mi wyjaśnić własnymi słowami i popraw mnie, jeśli się mylę. To, co widzę, to to, że statyczne _emptyArray pozostało w tyle. Ponieważ _emptyArray jest statyczny, zawsze będzie korzeniem pustej tablicy i dlatego nigdy nie będzie zbierać śmieci. – cchampion