Вопросы по GC
От: Anton Batenev Россия https://github.com/abbat
Дата: 17.11.05 03:35
Оценка:
Hello, All!

Чтение доков и лазание по интернету так и не помогло. Объясните тем, кто на бронепоезде.

* Для того, чтобы GC сам удалял объект, должен ли я его наследовать от Object (или его производной)?
* Удаляет ли GC массивы простых объектов (int, enum)?
* Приводит ли вызов Dispose к удалению объекта? Если да, то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны? Будет ли полезным после Dispose вызвать GC.Collect?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re: Вопросы по GC
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.11.05 03:47
Оценка: 8 (1) +5
Здравствуйте, Anton Batenev, Вы писали:

Список вопросов говорит о том, что ты вообще слабо понимашь что такое ЖЦ и как он работает. Очень советую почитать Рихтера.

AB>* Для того, чтобы GC сам удалял объект, должен ли я его наследовать от Object (или его производной)?


"Он" — это объект? Ну, да создать наследника ЖЦ в дотнете все равно невозможно. Так что будем считать, что "да".

Ты физически не сможешь создать объект не унаследованный от object. Даже если ты не укажешь ни какого родителя, класс все равнь будет наследником object. Исключением являются вэлью-типы, но и они виртуально наследуются от object.

AB>* Удаляет ли GC массивы простых объектов (int, enum)?


ЖЦ вообще ничего не удаляет. Идея ЖЦ в том, что все недоступные объекты автоматически мертвы, а значит место отведенное под них свободно. ЖЦ никода не интересуется тем какие объекты метрвы. Он интересуется тем какие объекты живы.

AB>* Приводит ли вызов Dispose к удалению объекта?


Нет. Dispose — это паттерн призванный облегчить контроль неуправляемых ресурсов (например, хндлов файлов). Иными словами это просто метод и соглашение о том, что после того как объект стал не нужен нужно вызвать этот метод.

AB> Если да,


Нет, но...

AB>то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?


Не просто рекомендуется, а крайне настоятельно рекомендуется. Друго дело, что рекомендуется делать это неявно, а через использование конструкции using (в C#).

AB> Будет ли полезным после Dispose вызвать GC.Collect?


Dispose будет полезен везде где он не вреден. А вот GC.Collect вреден везде кроме тестов и очень редких случаев хаков.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Вопросы по GC
От: krasin Россия  
Дата: 17.11.05 03:49
Оценка: 8 (1)
Здравствуйте, Anton Batenev, Вы писали:


AB>Чтение доков и лазание по интернету так и не помогло. Объясните тем, кто на бронепоезде.


AB>* Для того, чтобы GC сам удалял объект, должен ли я его наследовать от Object (или его производной)?

Если Вы находитесь в C#, то у Вас любой объект является наследником Object. Кроме того, любой объект будет собираться сборщиком мусора.
Или речь про Managed C++?

AB>* Удаляет ли GC массивы простых объектов (int, enum)?

Опять же, int и enum являются нормальными типами (в частности, являются наследниками Object) и собираются сборщиком мусора.

AB>* Приводит ли вызов Dispose к удалению объекта?

Нет, не приводит.

AB> Если да, то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?

Рекомендуется.

AB> Будет ли полезным после Dispose вызвать GC.Collect?

GC.Collect самому вызывать, как правило, не нужно.
Re[2]: Вопросы по GC
От: Anton Batenev Россия https://github.com/abbat
Дата: 17.11.05 05:07
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Список вопросов говорит о том, что ты вообще слабо понимашь что такое ЖЦ и как он работает. Очень советую почитать Рихтера.


Ты прав, совершенно не понимаю. Много чего понаписано итого образовалась в голове каша.

AB>>* Удаляет ли GC массивы простых объектов (int, enum)?

VD>ЖЦ вообще ничего не удаляет. Идея ЖЦ в том, что все недоступные объекты автоматически мертвы, а значит место отведенное под них свободно. ЖЦ никода не интересуется тем какие объекты метрвы. Он интересуется тем какие объекты живы.

М... не понятно.

В каком случае объект мертв, в каком жив? Если под живым объектом понимается используемый на данный момент объект, то зачем им интересуется GC?

AB>>то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?

VD>Не просто рекомендуется, а крайне настоятельно рекомендуется. Друго дело, что рекомендуется делать это неявно, а через использование конструкции using (в C#).

Это ведь не всегда возможно, например, для полей класса. Ну да ладно, не обломаюсь прописать ручками.

AB>> Будет ли полезным после Dispose вызвать GC.Collect?

VD>Dispose будет полезен везде где он не вреден. А вот GC.Collect вреден везде кроме тестов и очень редких случаев хаков.

ОК. Еще вопрос. Предположим

class MyClass1
{
    public MyClass1
    {
    }
}


class MyClass2
{
    public MyClass1 Field1;
    
    public MyClass2 ()
    {
        Field1 = new MyClass1();
    }
}

// Как сие корректно удалить?
MyClass2 cls = new MyClass2();


Как сие корректно удалить? Т.е., нужно ли реализовывать в MyClass2 и в MyClass1 метод Dispose (или еще чего-то)?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[2]: Вопросы по GC
От: Anton Batenev Россия https://github.com/abbat
Дата: 17.11.05 05:25
Оценка:
Здравствуйте, krasin, Вы писали:

AB>>* Приводит ли вызов Dispose к удалению объекта?

K>Нет, не приводит.
AB>> Если да, то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?
K>Рекомендуется.

ОК. По логике, Dispose можно прировнять тождественным деструктору C++ — вызвал Dispose и можешь забыть про объект (почти полная аналогия с delete). C типами, унаследоваными от Object — там я понял вообще ничего не вызовешь. Если реализовать деструктор в классе, то он вызывается когда хочет (а что будет, если его не реализовывать?). Но вот я не могу понять, как удаляются "составные" типы из FW? Т.е., например:


DbDataAdapter adapter = new SqlDataAdapter();

adapter.SelectCommand = new SqlCommand();
adapter.UpdateCommand = new SqlCommand();
adapter.DeleteCommand = new SqlCommand();

// что-то делаем

// вот после / перед этим надо писать:
//
// adapter.SelectCommand.Dispose();
// adapter.UpdateCommand.Dispose();
// adapter.DeleteCommand.Dispose();
//
// или нет и это уже забота DbDataAdapter?

adapter.Dispose();
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[3]: Вопросы по GC
От: ie Россия http://ziez.blogspot.com/
Дата: 17.11.05 05:34
Оценка: 8 (1)
Здравствуйте, Anton Batenev, Вы писали:

Постараюсь ответить за Влада, надеюсь он не обидется

VD>>Список вопросов говорит о том, что ты вообще слабо понимашь что такое ЖЦ и как он работает. Очень советую почитать Рихтера.


AB>Ты прав, совершенно не понимаю. Много чего понаписано итого образовалась в голове каша.


Читаем сперва здесь
Автор(ы): Игорь Ткачев
Дата: 06.12.2002
Алгоритм работы сборщика мусора (garbage collector, далее просто GC), являющегося частью CLR, подробно описан в книге Джефри Рихтера (Jeffrey Richter) «Applied Microsoft .NET Framework Programming». Мы не будем приводить здесь столь же подробное описание этого алгоритма, но обязательно остановимся на некоторых ключевых моментах.
(если есть возможность почитать Рихтера, то лучше его), что осталось непонятно — спрашиваем.

AB>>>* Удаляет ли GC массивы простых объектов (int, enum)?

VD>>ЖЦ вообще ничего не удаляет. Идея ЖЦ в том, что все недоступные объекты автоматически мертвы, а значит место отведенное под них свободно. ЖЦ никода не интересуется тем какие объекты метрвы. Он интересуется тем какие объекты живы.

AB>М... не понятно.


AB>В каком случае объект мертв, в каком жив?


Если на объект есть хотя бы одна ссылка — объект жив, иначе — мертв.

AB>Если под живым объектом понимается используемый на данный момент объект, то зачем им интересуется GC?


GC нуждается в живых объектах, для переноса их в другое покаление или же дефрагментации в случае максимального покаления.

AB>>>то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?


VD>>Не просто рекомендуется, а крайне настоятельно рекомендуется. Друго дело, что рекомендуется делать это неявно, а через использование конструкции using (в C#).


AB>Это ведь не всегда возможно, например, для полей класса. Ну да ладно, не обломаюсь прописать ручками.


Как показывает практика (не считаем кривой дизайн практикой) — поля объкта не нужны в том и только в том случае случае, когда не нужен сам объект. Т.о. вызов Dispose у объекта класса, должен влечь за собой вызов Dispose у полей классы которых имплементируют IDisposable.

AB>>> Будет ли полезным после Dispose вызвать GC.Collect?

VD>>Dispose будет полезен везде где он не вреден. А вот GC.Collect вреден везде кроме тестов и очень редких случаев хаков.

AB>ОК. Еще вопрос. Предположим


AB>
AB>class MyClass1
AB>{
AB>    public MyClass1
AB>    {
AB>    }
AB>}


AB>class MyClass2
AB>{
AB>    public MyClass1 Field1;
    
AB>    public MyClass2 ()
AB>    {
AB>        Field1 = new MyClass1();
AB>    }
AB>}

AB>// Как сие корректно удалить?
AB>MyClass2 cls = new MyClass2();
AB>


AB>Как сие корректно удалить? Т.е., нужно ли реализовывать в MyClass2 и в MyClass1 метод Dispose (или еще чего-то)?


Удалить детерминированно — никак, читай статью. Для освобождения неуправляемых ресурсов (если таковые имеются) — нужно!
Превратим окружающую нас среду в воскресенье.
Re[3]: Вопросы по GC
От: ie Россия http://ziez.blogspot.com/
Дата: 17.11.05 05:49
Оценка: 8 (1)
Здравствуйте, Anton Batenev, Вы писали:

AB>Здравствуйте, krasin, Вы писали:


AB>>>* Приводит ли вызов Dispose к удалению объекта?

K>>Нет, не приводит.
AB>>> Если да, то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?
K>>Рекомендуется.

AB>ОК. По логике, Dispose можно прировнять тождественным деструктору C++ — вызвал Dispose и можешь забыть про объект (почти полная аналогия с delete).


Нет, нет и нет! Никакой аналогии с delete тут и в помине нет.

AB>C типами, унаследоваными от Object — там я понял вообще ничего не вызовешь.


Есть 2 способа это сделать:
1. Сделать имплементацию интерфейса IDisposable у этих классов.
2. Не делать имплементацию интерфейса IDisposable у этих классов, но при этом добавить метод Dispose().
Второй способ крайне не рекомендую, ибо конструкция using недоступна, да и тем, кому посчисливится работать с такими классами будет не тривиально понять, что же такое хотел сказать автор.

AB>Если реализовать деструктор в классе, то он вызывается когда хочет .


Деструкторов как таковых нет, есть так называемые финалайзеры. Он вызовется ЖЦ, когда тот займется сборкой мусора.

AB>(а что будет, если его не реализовывать?)


(если объект не содержит анменеджед ресурсов, то ничего не будет)

AB>Но вот я не могу понять, как удаляются "составные" типы из FW? Т.е., например:


AB>

AB>DbDataAdapter adapter = new SqlDataAdapter();

AB>adapter.SelectCommand = new SqlCommand();
AB>adapter.UpdateCommand = new SqlCommand();
AB>adapter.DeleteCommand = new SqlCommand();

AB>// что-то делаем

AB>// вот после / перед этим надо писать:
AB>//
AB>// adapter.SelectCommand.Dispose();
AB>// adapter.UpdateCommand.Dispose();
AB>// adapter.DeleteCommand.Dispose();
AB>//
AB>// или нет и это уже забота DbDataAdapter?

AB>adapter.Dispose();

AB>


DbDataAdapter не должен вызывать Dispose у команд хотя бы по тому, что это объекты пришли к нему из вне и могут быть нужны еще кому-то кроме него.
Превратим окружающую нас среду в воскресенье.
Re: Вопросы по GC
От: Andrbig  
Дата: 17.11.05 06:46
Оценка: 8 (1)
Здравствуйте, Anton Batenev, Вы писали:

AB>Hello, All!


AB>Чтение доков и лазание по интернету так и не помогло. Объясните тем, кто на бронепоезде.


Для начала здесь
Автор(ы): Игорь Ткачев
Дата: 06.12.2002
Алгоритм работы сборщика мусора (garbage collector, далее просто GC), являющегося частью CLR, подробно описан в книге Джефри Рихтера (Jeffrey Richter) «Applied Microsoft .NET Framework Programming». Мы не будем приводить здесь столь же подробное описание этого алгоритма, но обязательно остановимся на некоторых ключевых моментах.
. Далее по тексту под "удаление" я понимаю "пометка куска памяти как свободного".

AB>* Для того, чтобы GC сам удалял объект, должен ли я его наследовать от Object (или его производной)?


Расслабься. GC сам все удалит, когда на твой объект никто не будет ссылаться (в статье описано подробнее).

AB>* Удаляет ли GC массивы простых объектов (int, enum)?


Да.

AB>* Приводит ли вызов Dispose к удалению объекта?


Нет.

AB>Если да, то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?


GC сработает неизвестно когда. Если у тебя объект держит ресурсы (коннект к базе например), то .net-ный стиль постоянно создавать объекты очень быстро приведет к исчерпанию ресурса. Для стандартизации выхода из этой ситуации придуман интерфейс IDisposable. .Net сама его не зовет, его надо вызывать по старинке, врукопашную!

AB>Будет ли полезным после Dispose вызвать GC.Collect?


Нет.
Re[4]: Вопросы по GC
От: Anton Batenev Россия https://github.com/abbat
Дата: 17.11.05 06:58
Оценка:
Здравствуйте, ie, Вы писали:

AB>>C типами, унаследоваными от Object — там я понял вообще ничего не вызовешь.

ie>Есть 2 способа это сделать:
ie>1. Сделать имплементацию интерфейса IDisposable у этих классов.
ie>2. Не делать имплементацию интерфейса IDisposable у этих классов, но при этом добавить метод Dispose().
ie>Второй способ крайне не рекомендую, ибо конструкция using недоступна, да и тем, кому посчисливится работать с такими классами будет не тривиально понять, что же такое хотел сказать автор.


Т.е., если я буду реализовывать каждый свой класс в виде:

public class MyClass : IDisposable
{
    public ManagedResource   Resource1; // managed ресурс, реализующий IDisposable
    public UnManagedResource Resource2; // unmanaged ресурс, типа HANDLE и им подобных

    public MyClass ()
    {
        Resource1 = new ManagedResource();
        Resource2 = CreateUnManagedResource();
    }

    ~MyClass ()
    {
        Dispose(false);
    }

    private void Dispose (bool disposing)
    {
        // managed
        if (disposing)
        {
            if (Resource1 != null)
            {
                Resource1.Dispose();
                Resource1 = null;
            }
        }
        
        // unmanaged
        if (Resource2 != null)
        {
            FreeUnManagedResource(Resource2);
            Resource2 = null;
        }

        // не требуется вызывать ~MyClass() из GC
        GC.SuppressFinalize(this);
    }
        
    public void Dispose ()
    {
        Dispose(true);
    }
}


То этого будет более чем достаточно и правильно (корректно)?


AB>>Если реализовать деструктор в классе, то он вызывается когда хочет .

ie>Деструкторов как таковых нет, есть так называемые финалайзеры. Он вызовется ЖЦ, когда тот займется сборкой мусора.
AB>>(а что будет, если его не реализовывать?)
ie>(если объект не содержит анменеджед ресурсов, то ничего не будет)


Т.е. я без всяких Dispose и прочих могу плодить объекты и "забывать" о них, и, когда надо, ЖЦ сам разберется на кого есть ссылки, на кого уже нету и удалит ненужное? Тогда зачем вызовы Dispose настоятельно рекомендуются? А сколько он памяти скушает прежде чем возьмется за свою работу?


AB>>
AB>>
AB>>DbDataAdapter adapter = new SqlDataAdapter();
AB>>
AB>>adapter.SelectCommand = new SqlCommand();
AB>>adapter.UpdateCommand = new SqlCommand();
AB>>adapter.DeleteCommand = new SqlCommand();
AB>>
AB>>// что-то делаем
AB>>
AB>>// вот после / перед этим надо писать:
AB>>//
AB>>// adapter.SelectCommand.Dispose();
AB>>// adapter.UpdateCommand.Dispose();
AB>>// adapter.DeleteCommand.Dispose();
AB>>//
AB>>// или нет и это уже забота DbDataAdapter?
AB>>
AB>>adapter.Dispose();
AB>>
AB>>


ie>DbDataAdapter не должен вызывать Dispose у команд хотя бы по тому, что это объекты пришли к нему из вне и могут быть нужны еще кому-то кроме него.


OK. Тогда так:

DbDataAdapter adapter = new SqlDataAdapter();

adapter.SelectCommand = new SqlCommand();
adapter.SelectCommand.Text = "SELECT * FROM dual";

SqlCommandBuilder command_builder = new SqlCommandBuilder(adapter);

// тут что-то делаем

// вот как тут будет правильно?
command_builder.Dispose();
adapter.Dispose();


В данном примере UpdateCommand и DeleteCommand создаст у объекта adapter объект command_builder. Кто их должен кого "диспозить" и в каком порядке?

З.Ы. Мое непонимание идет корнями из С++, где ответственность за создание и удаление была четко регламентирована. В C# я не вижу четкой логики — кто создает объект и кто его должен удалять и в каком порядке.

P.P.S. Статья на сайте RSDN не помогла прояснить эти, может быть элементарные, вопросы. Только еще больше запутала. Рихтера читать на английском немного тяжеловато, если есть e-book на русском, то хотелось бы его получить — почитаю с превиликим удовольствием.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[2]: Вопросы по GC
От: Anton Batenev Россия https://github.com/abbat
Дата: 17.11.05 07:20
Оценка:
Здравствуйте, Andrbig, Вы писали:

AB>>Чтение доков и лазание по интернету так и не помогло. Объясните тем, кто на бронепоезде.

A>Для начала здесь
Автор(ы): Игорь Ткачев
Дата: 06.12.2002
Алгоритм работы сборщика мусора (garbage collector, далее просто GC), являющегося частью CLR, подробно описан в книге Джефри Рихтера (Jeffrey Richter) «Applied Microsoft .NET Framework Programming». Мы не будем приводить здесь столь же подробное описание этого алгоритма, но обязательно остановимся на некоторых ключевых моментах.
. Далее по тексту под "удаление" я понимаю "пометка куска памяти как свободного".


Этот свободный кусок отдается системе (другим програмам)?

AB>>* Для того, чтобы GC сам удалял объект, должен ли я его наследовать от Object (или его производной)?

A>Расслабься. GC сам все удалит, когда на твой объект никто не будет ссылаться (в статье описано подробнее).

В статье так же упоминается, что реализуя "~class_name" я могу повесить объект в памяти навсегда. Как это можно сделать и как избежать — не совсем понятно. Понятно только, что реализация метода "~class_name" крайне не желательна. В то же самое время, в примере из MSDN его преспокойно реализуют.

AB>>Если да, то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?

A>GC сработает неизвестно когда. Если у тебя объект держит ресурсы (коннект к базе например), то .net-ный стиль постоянно создавать объекты очень быстро приведет к исчерпанию ресурса. Для стандартизации выхода из этой ситуации придуман интерфейс IDisposable. .Net сама его не зовет, его надо вызывать по старинке, врукопашную!

Т.е. GC может вызвать только "~class_name". Когда он это сделает — не известно. Я же, для того, чтобы освобождать ресурсы (например, коннекты), могу реализовать в своих классах хоть Dispose, хоть Close, хоть SuperBuperResourceCleaner — пофигу (но в хорошем тоне принято Dispose в реализации наследника от IDisposable) — я этим просто освобождаю ресурсы. Ресурсы не в смысле памяти, а в смысле, например, закрываю коннекты к базе, закрываю открытые файлы и прочее. Я все правильно понимаю?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[3]: Вопросы по GC
От: GlebZ Россия  
Дата: 17.11.05 07:21
Оценка: 8 (1)
Здравствуйте, Anton Batenev, Вы писали:

AB>В каком случае объект мертв, в каком жив? Если под живым объектом понимается используемый на данный момент объект, то зачем им интересуется GC?

Если объект достижим, то есть если существует хоть одна ссылка из объекта являющимся живым, то он живой. Если ни одной ссылки нет, то это всего лишь область памяти, которую GC будет считать свободной. Исключение, если существует метод finalize. В случае если существует метод finalize(в С# он описывается как деструктор), то GC должно вызвать этот метод при сборке мусора. Теоретически там существует возможность сново объявить объект живым присвоив ссылку на него какому-нибудь другому живому объекту. Но напрямую, не в паттерне Dispose finalize не используется. Это обычно последняя помощь для вызова отложенного Dispose в случае если это забыл сделать пользователь.

AB>>>то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?

VD>>Не просто рекомендуется, а крайне настоятельно рекомендуется. Друго дело, что рекомендуется делать это неявно, а через использование конструкции using (в C#).
AB>Это ведь не всегда возможно, например, для полей класса. Ну да ладно, не обломаюсь прописать ручками.
Dispose действительно для класса. Но нужно учитывать что освобождать память не нужно. GC это делает автоматически. В подавляющем большинстве случаев Dispose используется только для освобождения unmanaged ресурсов.

AB>>> Будет ли полезным после Dispose вызвать GC.Collect?

VD>>Dispose будет полезен везде где он не вреден. А вот GC.Collect вреден везде кроме тестов и очень редких случаев хаков.
GC.Collect — не вызывает Dispose. Dispose — это паттерн который эмулирует детерменированный деструктор. Это правило выполняемое пользователями объекта. В большинстве случаев, если ты видишь что у объекта есть интерфейс IDisposable, то надо вызывать Dispose. В основном для работы с Dispose используют операцию using.

AB>ОК. Еще вопрос. Предположим


AB>
AB>class MyClass1
AB>{
AB>    public MyClass1
AB>    {
AB>    }
AB>}
AB>class MyClass2
AB>{
AB>    public MyClass1 Field1;
    
AB>    public MyClass2 ()
AB>    {
AB>        Field1 = new MyClass1();
AB>    }
AB>}

AB>// Как сие корректно удалить?
AB>MyClass2 cls = new MyClass2();
AB>


AB>Как сие корректно удалить? Т.е., нужно ли реализовывать в MyClass2 и в MyClass1 метод Dispose (или еще чего-то)?

А зачем удалять? Как только ссылок на cls не будет — объекты будут не более чем область памяти которая при сборку мусора будет помечена как свободная.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Вопросы по GC
От: Anton Batenev Россия https://github.com/abbat
Дата: 17.11.05 07:29
Оценка:
Здравствуйте, Andrbig, Вы писали:

AB>Я все правильно понимаю?


Так же, если я все правильно понимаю, то:

class MyClass : public BaseObject
{
    public SomeObject obj1;
    public SomeObject obj2;
    
    public MyClass ()
    {
        obj1 = new SomeObject();
        obj2 = new SomeObject();
    }
    
    ~MyClass ()
    {
    }
};


Когда GC вызовет MyClass::~MyClass это вовсе не значит, что перед этим будут вызваны obj1::~obj1 и obj2::~obj2? Так же, это не значит, что после вызова MyClass::~MyClass будет вызван BaseObject::~BaseObject? И так же это значит, что порядок вызовов деструкторов (финализаторов) не определен, и может быть разделен на большом промежутке времени, в течении которого могут быть вызваны и деструкторы (финализаторы) других объектов с данным не свзаных?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[4]: Вопросы по GC
От: GlebZ Россия  
Дата: 17.11.05 07:59
Оценка: 8 (1)
Здравствуйте, Anton Batenev, Вы писали:

AB>Когда GC вызовет MyClass::~MyClass это вовсе не значит, что перед этим будут вызваны obj1::~obj1 и obj2::~obj2?

Не обязательно перед этим, но будут. При той же сборке мусора.
AB>Так же, это не значит, что после вызова MyClass::~MyClass будет вызван BaseObject::~BaseObject?
Должен быть один finalize на объект.
AB>И так же это значит, что порядок вызовов деструкторов (финализаторов) не определен, и может быть разделен на большом промежутке времени, в течении которого могут быть вызваны и деструкторы (финализаторы) других объектов с данным не свзаных?
Да. Но при этом желательно учитывать следующую вещь. Финализаторы как таковые практически никогда не используются. Ну нету особого смысла в них при наличии Dispose. finalize — это последний довод чтобы исправить ошибку программиста.
А учитывая что не нужно освобождать managed ресурсы, обнулять ссылки и т.д., то и Dispose используется значительно реже чем в C++. 90 процентов кода не содержит Dispose.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Вопросы по GC
От: GlebZ Россия  
Дата: 17.11.05 07:59
Оценка: 8 (1)
Здравствуйте, Anton Batenev, Вы писали:

AB>Здравствуйте, Andrbig, Вы писали:


AB>>>Чтение доков и лазание по интернету так и не помогло. Объясните тем, кто на бронепоезде.

A>>Для начала здесь
Автор(ы): Игорь Ткачев
Дата: 06.12.2002
Алгоритм работы сборщика мусора (garbage collector, далее просто GC), являющегося частью CLR, подробно описан в книге Джефри Рихтера (Jeffrey Richter) «Applied Microsoft .NET Framework Programming». Мы не будем приводить здесь столь же подробное описание этого алгоритма, но обязательно остановимся на некоторых ключевых моментах.
. Далее по тексту под "удаление" я понимаю "пометка куска памяти как свободного".


AB>Этот свободный кусок отдается системе (другим програмам)?

Ессно. Еще не следует забывать что память под живые объекты при сборке дефрагментируется и переносится из поколение в поколение. Для C++ это выглядит кощунственным.

AB>>>* Для того, чтобы GC сам удалял объект, должен ли я его наследовать от Object (или его производной)?

A>>Расслабься. GC сам все удалит, когда на твой объект никто не будет ссылаться (в статье описано подробнее).

AB>В статье так же упоминается, что реализуя "~class_name" я могу повесить объект в памяти навсегда. Как это можно сделать и как избежать — не совсем понятно. Понятно только, что реализация метода "~class_name" крайне не желательна. В то же самое время, в примере из MSDN его преспокойно реализуют.

Если у тебя в финалайзе проскочил бесконечный цикл — то финалайзы дальше не будут вызываться. Есть такая особенность. Обычно реализация finalize — это тупой вызов Dispose метода.

AB>>>Если да, то рекомендуется ли вызывать Dispose для объектов, которые точно больше не нужны?

A>>GC сработает неизвестно когда. Если у тебя объект держит ресурсы (коннект к базе например), то .net-ный стиль постоянно создавать объекты очень быстро приведет к исчерпанию ресурса. Для стандартизации выхода из этой ситуации придуман интерфейс IDisposable. .Net сама его не зовет, его надо вызывать по старинке, врукопашную!

AB>Т.е. GC может вызвать только "~class_name". Когда он это сделает — не известно. Я же, для того, чтобы освобождать ресурсы (например, коннекты), могу реализовать в своих классах хоть Dispose, хоть Close, хоть SuperBuperResourceCleaner — пофигу (но в хорошем тоне принято Dispose в реализации наследника от IDisposable) — я этим просто освобождаю ресурсы. Ресурсы не в смысле памяти, а в смысле, например, закрываю коннекты к базе, закрываю открытые файлы и прочее. Я все правильно понимаю?

Да.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Вопросы по GC
От: Surviver  
Дата: 17.11.05 09:48
Оценка: 15 (2)
Здравствуйте, Anton Batenev, Вы писали:

AB>P.P.S. Статья на сайте RSDN не помогла прояснить эти, может быть элементарные, вопросы. Только еще больше запутала. Рихтера читать на английском немного тяжеловато, если есть e-book на русском, то хотелось бы его получить — почитаю с превиликим удовольствием.


Имеется, 18 Mb. Смогу вечером куда-то выложить.
Оставьте, плз, ICQ.
Re[6]: Вопросы по GC
От: Anton Batenev Россия https://github.com/abbat
Дата: 17.11.05 09:55
Оценка:
Здравствуйте, Surviver, Вы писали:

AB>>P.P.S. Статья на сайте RSDN не помогла прояснить эти, может быть элементарные, вопросы. Только еще больше запутала. Рихтера читать на английском немного тяжеловато, если есть e-book на русском, то хотелось бы его получить — почитаю с превиликим удовольствием.

S>Имеется, 18 Mb. Смогу вечером куда-то выложить.
S>Оставьте, плз, ICQ.

По ICQ меня будет тяжело поймать. Если можете выложить — выкладывайте куда душе вздумается — выкачаю. Буду премного благодарен. Если что, мыло — мои имя и фамилия латиницей слитно (поле "ОТ" без пробелов) на yandex.ru.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[7]: Вопросы по GC
От: Surviver  
Дата: 17.11.05 09:57
Оценка:
Здравствуйте, Anton Batenev, Вы писали:

AB>По ICQ меня будет тяжело поймать. Если можете выложить — выкладывайте куда душе вздумается — выкачаю. Буду премного благодарен. Если что, мыло — мои имя и фамилия латиницей слитно (поле "ОТ" без пробелов) на yandex.ru.


Хорошо.
Re[3]: Вопросы по GC
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.11.05 12:33
Оценка: 8 (1)
AB>Ты прав, совершенно не понимаю. Много чего понаписано итого образовалась в голове каша.

Так вот, чтобы получить стройную картину почитай Рихтера. Там изложение хотя и поверхностное, но стройное.

AB>В каком случае объект мертв, в каком жив? Если под живым объектом понимается используемый на данный момент объект, то зачем им интересуется GC?


Полное объяснение займет слишком много места. К тому же оно уже не раз было. Воспользуйся поиском. На пальцах:
ЖЦ переодически запускается чтобы освободить память для новых объектов. При этом он проверяет так называемые корни ЖЦ — глобальные ссылки, стек/регистры (локальные переменные) и очередь финализации. ЖЦ знает на что указывают эти корни. Далее ЖЦ рекурсивно пробегается по ссылкам пытаясь построить граф живых объектов. На мертвые объекты ему плевать. Далее происходит одно из двух.
1. Если собирается первое или нулевое поколение, то живые объекты копируются в хип более старшего поколения.
2. Если собирается второе поколение, то живые объекты сдвигаются в начало хипа второго поколения.

Отдельным случаем являются объекты большого размера (если не ошибаюсь, объекты превышающие 80 байт). Они сразу помещаются во второе поколение. Более того для них используется отдельный хип — LOH (Large Objects Heap). Этот хип устроен похоже на хип языка С. Дефрагментация в нем не производится, а пустые блоки объеденяются в случае если по отдельности их размер не достаточен.

AB>Это ведь не всегда возможно, например, для полей класса. Ну да ладно, не обломаюсь прописать ручками.


Для полей классов нужно вызвать диспоз вручную из диспоза самого класса. Однако сама по себе такая ситуация не хороша. Для контроля ресурсов нужно стараться создавать отдельные классы контролирующие не более одного ресурса. Тогда и вложенности не получится. Исключением являются контейнеры вроде форм, но это скорее экзотика.

AB>ОК. Еще вопрос. Предположим


AB>
AB>class MyClass1
AB>{
AB>    public MyClass1
AB>    {
AB>    }
AB>}


AB>class MyClass2
AB>{
AB>    public MyClass1 Field1;
    
AB>    public MyClass2 ()
AB>    {
AB>        Field1 = new MyClass1();
AB>    }
AB>}

AB>// Как сие корректно удалить?
AB>MyClass2 cls = new MyClass2();
AB>


AB>Как сие корректно удалить?


Никак. Это просто не требуется. ЖЦ — это система автоматического управления памятью. Так что в общем случае об управление памятью вообще не нужно думать.

AB> Т.е., нужно ли реализовывать в MyClass2 и в MyClass1 метод Dispose (или еще чего-то)?


Нет. Диспоз в основном нужен для контроля ресурсов ОС. Очень редким случаем конторля в управляемом мире является контроль отключения событий от синглтон-объектов (глобальных объектов). Нужно это так как глобальные объекты являются корнями ЖЦ, а подключение событий создают ссылки. Причем программист может об этом не догадываться, так что ссылка для него в этом случае не очевидна. В остальном конроль не нужен, память управляется автоматом. В этом собственно и заключается смысл ЖЦ. Он практически полностью снимает с программиста работу по управлению памятью. Высвободившееся время и силы можно потратить на решение основной задачи.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Вопросы по GC
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.11.05 12:33
Оценка: +2
Здравствуйте, GlebZ, Вы писали:

GZ>Если объект достижим, то есть если существует хоть одна ссылка из объекта являющимся живым, то он живой. Если ни одной ссылки нет, то это всего лишь область памяти, которую GC будет считать свободной. Исключение, если существует метод finalize. В случае если существует метод finalize(в С# он описывается как деструктор), то GC должно вызвать этот метод при сборке мусора. Теоретически там существует возможность сново объявить объект живым присвоив ссылку на него какому-нибудь другому живому объекту. Но напрямую, не в паттерне Dispose finalize не используется. Это обычно последняя помощь для вызова отложенного Dispose в случае если это забыл сделать пользователь.


Финализируемые объекты не являются исключением. Алгоритм очень прост. Граф живых объектов рассчитывается путем рекурсивного перебора начиная с корней ЖЦ. Корнями являются:
1. Глобальные переменные.
2. Регистры и области стека попавшие в карту ЖЦ (разные для разных точек программы). Говоря проще — это локальные переменные.
3. Ссылки из более старших поколений.
4. Очередь финализации.

Собственно п. 4 нам и интересен в данном случае. Когда создается объект реализующий финализатор, то ссылка на него автоматически помещается в очередь финализации и даже если на объект нет ни одной ссылки он все равно считается достижимым, так как ссылка на него есть в очереди финализации. Именно по этому любой финилизирвемый объект по-умолчанию продвигается в первое поколение. Чтобы этого избежать можно в Диспозе вызвать GC.SuppressFinalize(this).
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Вопросы по GC
От: GlebZ Россия  
Дата: 17.11.05 12:43
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Отдельным случаем являются объекты большого размера (если не ошибаюсь, объекты превышающие 80 Кбайт).

Букву К забыл.

С уважением, Gleb.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.