Сборщик мусора C #, вопрос об «очистке» объектов - PullRequest
4 голосов
/ 15 июня 2011

Я прочитал некоторые сведения о сборке мусора (как это работает и т. Д.).Я пытался понять, как это работает на моих примерах, но я думаю, что у меня проблема.Я знаю, что сборщик мусора запускается, когда:
недостаточно памяти,
вы вызываете GC.Collect ().
Это мой код:

public partial class Form1 : Form
{
    public Testing _d;
    public Boolean _first = false;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (!_first)
        {
            _d = new Testing();
            int test = _d.DoSomething("example");
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        _first = true;
    }

    private void button3_Click(object sender, EventArgs e)
    {
        //if (_first)
        //{
        //    _d = null;
        //}
        GC.Collect();
    }
}

public class Testing
{
    private ASCIIEncoding _ascii;
    private bool _disposed = false;

    public Testing()
    {
        _ascii = new ASCIIEncoding();
    }

    public int DoSomething(string message)
    {
        return _ascii.GetByteCount(message);
    }
}

Когда я нажимаю кнопку1, я создаю новый объект Тестирование._d является ссылкой на этот новый объект.Я сбрасываю память с помощью JetBrains dotTrace Memory и вижу, что этот новый объект существует.После нажатия кнопки 2 я устанавливаю для логического _first значение true, чтобы _d стало недоступным.В этот момент я подумал, что при запуске GC.Collect () GC «очистит» этот объект из стека, но я вижу, что он все еще существует.Я неправильно понял работу GC?или я делаю это неправильно?
Это работает, когда я устанавливаю _d = null;

Ответы [ 5 ]

8 голосов
/ 15 июня 2011

Нажатие кнопки 2 не делает _d недоступным.

ГХ собирает только объекты, на которые нет ссылок из корневого объекта.
Пока ваша форма имеет ссылку на _d, онане будут собраны.

4 голосов
/ 15 июня 2011

Установка first=false не делает экземпляр _d недоступным с точки зрения GC. Логически вы никогда не сможете использовать его снова, но на него все еще ссылаются в классе Form1.

Если бы кто-то снова установил first=true, разве вы не ожидали, что объект все еще можно будет использовать?

4 голосов
/ 15 июня 2011

Это потому, что _d является ссылкой на экземпляр Testing, который вы установили и никогда не очищаете._d по-прежнему указывает на объект в куче и будет поддерживать эту ссылку до тех пор, пока вы не очистите его (вызвав (_d = null).

Unreachable не означает, что _d не может быть назначен другому объекту, но скорее объект, находящийся в куче, не имеет шансов быть вызванным снова (так как в коде нет ссылок)

Поэтому GC не может его очистить, так как он может все еще использоваться позже в вашем коде.

3 голосов
/ 15 июня 2011

Вы неправильно поняли, как GC определяет достижимость объекта: любой объект, на который ссылается переменная в текущей локальной области видимости, любые статические переменные и любые переменные экземпляра объектов, которые достижимы, сами по себе являются "достижимыми" - посмотрите на нем в виде графа с упомянутыми выше переменными в качестве «корней» графа.

В вашем примере _d все еще содержит ссылку на ваш объект, поэтому он все еще доступен и не будет собирать мусор.

1 голос
/ 11 июля 2017

Если вы вызываете GC.Collect (), все объекты, независимо от того, сколько времени они были в памяти, считаются для сбора; однако объекты, на которые есть ссылки в управляемом коде, не собираются GC. Проверьте это

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...