Ситуация
Согласно этому принятому ответу , если " GC" видит "циклическую ссылку на 2 или более объектов, на которые не ссылаются никакие другие объекты или постоянныеGC обрабатывает, эти объекты будут собраны. "
Я хотел бы знать, работает ли сборка мусора для очень простой древовидной структуры, которая даже не имеет контента, только узлы дерева с родительскими и дочерними элементами-Рекомендации.
Представьте, что вы создаете корневой узел, добавляете к нему дочерний элемент, а затем дочерний элемент к дочернему элементу и т. Д. Так что на самом деле это не дерево, а скорее список (каждый узел имеет не более одного дочернего элемента и одного родительского элемента)).
Если мы затем удалим дочерний элемент root и все ссылки на узлы в поддереве этого дочернего элемента, как я понимаю ответ выше, сборщик мусора должен очистить поддерево.
Описание проблемы
Если вы посмотрите на Main-метод в тестовом коде ниже, когда запускает exe из Release-каталога, я получаю поведение, которое я ожидаю потребление памяти увеличивается до ~ 1 ГБ, затем снова уменьшается до ~ 27 МБ (после 1. GC.collect) и затем снова до ~ 27 МБ (для 2. GC.collect).
Теперькогда запускает его в отладчике потребление памяти для этого увеличивается до ~ 1 ГБ, а для 1.GC.collect потребление памяти остается на том же уровне, что и тогда, до 1,6 ГБ с использованием второго цикла forвремя от времени я наконец получаю OutOfMemoryException во втором цикле for.
Вопросы
Почему я получаю такое поведение в отладчике?
Shouldn '• Работает ли сборщик мусора во время отладки, мне не хватает информации о отладчике?
Примечания
- Я использую Visual Studio 2010 Express Edition
- Я вызываю только GC.Collect () дляконкретные цели тестирования здесь, чтобы убедиться, что сборка мусора должна была произойти. (Я не планирую использовать это нормально)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tree
{
class Program
{
static void Main(string[] args)
{
TreeNode root = new TreeNode(null); // the null-argument is the parent-node
TreeNode node = root;
for (int i = 0; i < 15000000; i++)
{
TreeNode child = new TreeNode(node);
node = child;
}
root.RemoveChild(root.Children[0] );
node = root;
GC.Collect();
for (int i = 0; i < 15000000; i++)
{
TreeNode child = new TreeNode(node);
node = child;
}
root.RemoveChild(root.Children[0]);
node = root;
GC.Collect();
Console.ReadLine();
}
}
}
Я включаю только следующий кодесли вы хотите проверить это сами, это не очень полезно
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Tree
{
class TreeNode
{
public TreeNode Parent { get; private set; }
public List<TreeNode> Children { get; set; }
public TreeNode(TreeNode parent)
{
// since we are creating a new node we need to create its List of children
Children = new List<TreeNode>();
Parent = parent;
if(parent != null) // the root node doesn't have a parent-node
parent.AddChild(this);
}
public TreeNode(TreeNode parent, List<TreeNode> children)
{
// since we are creating a new node we need to create its List of children
Children = new List<TreeNode>();
Parent = parent;
if (parent != null) // the root node doesn't have a parent-node
parent.AddChild(this);
Children = children;
}
public void AddChild(TreeNode child)
{
Children.Add(child);
}
public void RemoveChild(TreeNode child)
{
Children.Remove(child);
}
}
}