Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> GC.Collect 
V
    Опции темы
v00d00
Дата 2.2.2009, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 142
Регистрация: 28.12.2005

Репутация: нет
Всего: нет



Кто-нибудь может объяснить как работает этот метод сборщика мусора. В приведенном ниже коде, если удалить строчку с методом GC.KeepAlive(mt); программа начинает работать так, словно мутекс не создавался.

Код

bool MutexWasCreated;
            //создаем глобальный Mutex для предотвращения повторного запуска приложения
            Mutex mt = new Mutex(true, "BudPDMLibAdmin", out MutexWasCreated);
            if (MutexWasCreated)
            {
                
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                // Add the event handler for handling UI thread exceptions to the event.
                Application.ThreadException += new ThreadExceptionEventHandler(AppExceptionHandler.UIThreadException);
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
                try
                {
                    log4net.Config.XmlConfigurator.Configure();
                    if (log.IsInfoEnabled)
                        log.Info("===== " + BudPDMLib.Admin.Properties.Resources.cStrLogAppStarted + " " + Application.ExecutablePath + " =====");
                    Application.Run(new MainForm());
                    if (log.IsInfoEnabled)
                        log.Info("===== " + BudPDMLib.Admin.Properties.Resources.cStrLogAppFinished + " " + Application.ExecutablePath + " =====");
                }
                catch (Exception e)
                {
                    BaseAppUtils.ShowErrorProduct(e.Message);
                }
                //Не дать сборщику муссора удалить мутекс до завершения приложения
                GC.KeepAlive(mt);
            }
            else
            {
                BaseAppUtils.ShowWarningSimple(Properties.Resources.cStrWarningAlreadyRuning);
            }


Что  делает метод GC.KeepAlive() я могу понять по документации, меня интересует как метод, который вызывается после завершения программы может препятсявовать удалению объекта сборщиком мусора? Сложилось впечатление что это деректива препроцессору...

Это сообщение отредактировал(а) v00d00 - 2.2.2009, 13:13
PM MAIL   Вверх
emmanuil
Дата 3.2.2009, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: 1
Всего: 3



Цитата(v00d00 @  2.2.2009,  10:54 Найти цитируемый пост)
//Не дать сборщику муссора удалить мутекс до завершения приложения                GC.KeepAlive(mt);

Он не подбирается сборщиком, потому что на него ссылка имеется при вызове метода GC.KeepAlive(mt). Вот поэтому он и живет до конца приложения, т.е. пока не закроется главная форма в твоем случае.
А метод этот делает ссылку на указанный объект, делая его недоступным для сборщика мусора с момента начала текущей процедуры до вызова этого метода. Чтобы лучше понять это, нужно понять принципы работы GC.
PM MAIL   Вверх
v00d00
Дата 4.2.2009, 17:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 142
Регистрация: 28.12.2005

Репутация: нет
Всего: нет



Если бы я вместо этого метода обратился к свойству объекта, эффект был бы такой же? На этапе компиляции сгенерировался бы код, запрещаюший удаление этого объекта? Ведь по идее до завершения программы переменная-указатель будет продолжать лежать на стеке?

Цитата

А метод этот делает ссылку на указанный объект, делая его недоступным для сборщика мусора с момента начала текущей процедуры до вызова этого метода. Чтобы лучше понять это, нужно понять принципы работы GC.


Он делает ссылку на объект после того как он теоретически может быть уничтожен?
PM MAIL   Вверх
emmanuil
Дата 4.2.2009, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: 1
Всего: 3



Если бы ты использовал объект после закрытия гл. формы, то все время работы приложения он бы не уничтожился, так как на него будет ссылка. Объекты хранятся в куче, кроме структур value type - они хранятся в стеке и уничтожаются при выходи из области видимости автоматически. GC ходит по куче, считает ссылки и ликвидирует объекты. Уничтожение проходит в несколько этапов, это прочитать нужно.
Цитата(v00d00 @  4.2.2009,  15:10 Найти цитируемый пост)
Он делает ссылку на объект после того как он теоретически может быть уничтожен?
Да, только если и после этого на него не будет ссылок. Если нужно чтобы объект жил, то лучше написать GC.KeepAlive(mt); чем Mutex tmp = mt;

PM MAIL   Вверх
v00d00
Дата 4.2.2009, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 142
Регистрация: 28.12.2005

Репутация: нет
Всего: нет



Mutex mt = new Mutex(true, "BudPDMLibAdmin", out MutexWasCreated); Это строка находится выше на уровень вложенности, чем получивший управление код, следовательно переменная mt гарантированно будет лежать на стеке до завершения программы. 

Или сборщик видит что потом она нигде не используется и удаляет объект по ней?

Если переформулировать мои вопрос, то он будет выглядеть так: Почему сборщик удаляет объект под переменной, которая все еще лежит на стеке, но не используется? Ссылка то еще живая, и умрет только по выходу управления из функции.
PM MAIL   Вверх
emmanuil
Дата 4.2.2009, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: 1
Всего: 3



Цитата(v00d00 @  4.2.2009,  16:26 Найти цитируемый пост)
Mutex mt = new Mutex(true, "BudPDMLibAdmin", out MutexWasCreated); Это строка находится выше на уровень вложенности, чем получивший управление код, следовательно переменная mt гарантированно будет лежать на стеке до завершения программы. 
 Переменная всего лишь хранит в себе ссылку, а сам объект лежит не в стеке, а в куче. После создания мутекса при отсутствии GC.KeepAlive(mt); на созданный объект больше не ссылается не одна переменная и поэтому сборщик уничтожает объект за ненадобностью.
Цитата(v00d00 @  4.2.2009,  16:26 Найти цитируемый пост)
Или сборщик видит что потом она нигде не используется и удаляет объект по ней?
 Да, так он поступает с сылочными типами.
Цитата(v00d00 @  4.2.2009,  16:26 Найти цитируемый пост)
Если переформулировать мои вопрос, то он будет выглядеть так: Почему сборщик удаляет объект под переменной, которая все еще лежит на стеке, но не используется? Ссылка то еще живая, и умрет только по выходу управления из функции.

Это бы работал, если бы мутекс был структурой и хранился в стеке, тогда бы сборщик его не достал. Но он хранится в куче и поэтому сборщик его уничтожит, если на него не будет ссылок.

Почитай про ссылочные типы и типы значений и про сборщик, сразу станет понятнее.
PM MAIL   Вверх
Partizan
Дата 4.2.2009, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

Репутация: 8
Всего: 67



Цитата

следовательно переменная mt гарантированно будет лежать на стеке


v00d00, mt не будет лежать на стеке. Объект будет создан в куче


Цитата

Или сборщик видит что потом она нигде не используется и удаляет объект по ней?


Ага...сборщик умный...


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PashaPash
Дата 4.2.2009, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49



Цитата(v00d00 @  4.2.2009,  18:26 Найти цитируемый пост)
Mutex mt = new Mutex(true, "BudPDMLibAdmin", out MutexWasCreated); Это строка находится выше на уровень вложенности, чем получивший управление код, следовательно переменная mt гарантированно будет лежать на стеке до завершения программы. 

Или сборщик видит что потом она нигде не используется и удаляет объект по ней?

В debug JIT продлевает время жизни переменной до ее scope - чтобы в отладке можно было посмотреть значение после последнего использования. В release время жизни значительно сокращается smile


--------------------
PM MAIL WWW   Вверх
emmanuil
Дата 5.2.2009, 05:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: 1
Всего: 3



Цитата(PashaPash @  4.2.2009,  19:14 Найти цитируемый пост)
В debug JIT продлевает время жизни переменной до ее scope - чтобы в отладке можно было посмотреть значение после последнего использования. В release время жизни значительно сокращается 

На сколько я знаю, то JIT это способ компиляции и JIT  компиляторы. А за временем жизни объектов следит CLR - сборщик мусора. Как с этим справляется IDE мне доподленно не известно, возможно для переменных хранит ссылки на них во время отладки для показана сведений по ним.
PM MAIL   Вверх
PashaPash
Дата 5.2.2009, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

Репутация: 9
Всего: 49



Цитата(emmanuil @  5.2.2009,  05:44 Найти цитируемый пост)
На сколько я знаю, то JIT это способ компиляции и JIT  компиляторы. А за временем жизни объектов следит CLR - сборщик мусора. Как с этим справляется IDE мне доподленно не известно, возможно для переменных хранит ссылки на них во время отладки для показана сведений по ним. 

Насколько я знаю, сборщик мусора за временем жизни объектов не следит. Он тупо пробегается по дереву объектов начиная с корней "корням" и все, что не увидит, подметает. Перменные в стеке (ссылки), глобальные переменные, значения в регистрах - это корни. Лежит ли переменная в стеке в конкретный момент, или давно выброшена и не используется - определяется JIT. И именно JIT дает GC список смертников - GC Info. Вот краткая инструкция по наблюдению за процессом в дикой природе:
http://blogs.msdn.com/yunjin/archive/2005/05/15/417569.aspx

Это сообщение отредактировал(а) PashaPash - 5.2.2009, 10:39


--------------------
PM MAIL WWW   Вверх
WarHog
Дата 5.2.2009, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 20.10.2007
Где: Воронеж

Репутация: нет
Всего: 2



В подтверждение слов PashaPash - можно посмотреть еще у Рихтера - глава 20, часть называется "Сбор мусора и отладка". Там подробно расписываются особенности работы JIT-компилятора с /debug и /optimize сборками
--------------------
PM MAIL   Вверх
emmanuil
Дата 5.2.2009, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: 1
Всего: 3



Цитата(PashaPash @  5.2.2009,  08:38 Найти цитируемый пост)
Насколько я знаю, сборщик мусора за временем жизни объектов не следит. Он тупо пробегается по дереву объектов начиная с корней "корням" и все, что не увидит, подметает. Перменные в стеке (ссылки), глобальные переменные, значения в регистрах - это корни. Лежит ли переменная в стеке в конкретный момент, или давно выброшена и не используется - определяется JIT. И именно JIT дает GC список смертников - GC Info.:

Вот как раз сборщик и следит. Jit при генерации кода кроме прочего создает корни и никаких смертников не дает сборщику. Это сборщик сам определяет есть ли ссылки на объект или нет. Jit не занимается поиском смертников этим занимается как раз таки сборщик, маркирует и т.д.
Цитата(emmanuil @  5.2.2009,  03:44 Найти цитируемый пост)
 Как с этим справляется IDE мне доподленно не известно, возможно для переменных хранит ссылки на них во время отладки для показана сведений по ним.

Про отладку я и писал, что мне доподленно не известно, но как я и предполагал, хранит ссылки, но только не IDE а сам JIT, он генерит внутреннюю таблицу корней.

PM MAIL   Вверх
WarHog
Дата 5.2.2009, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 122
Регистрация: 20.10.2007
Где: Воронеж

Репутация: нет
Всего: 2



emmanuil, как я понимаю, при генерации машинного кода JIT-компилятор в генерируемой им внутренней таблице корней  указывает диапазон байт, в котором на данный корень есть ссылки. GC, находясь в определенном месте при вызове, смотрит, какие корни действительны в этой точке вызова, а какие - нет, именно по этой таблице, генерируемой JIT-компилятором
--------------------
PM MAIL   Вверх
v00d00
Дата 5.2.2009, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 142
Регистрация: 28.12.2005

Репутация: нет
Всего: нет



Спасибо за разъяснения, на будущее запомню, когда работаем с неуправляемым кодом, объекты с ресурсами нельзя позволять удлать сборщику.

И на сколько я понял метод KeepAlive на самом деле ничего не делает, просто в коде хранится смещение ссылки на стеке, которая указывает на объект, который лежит в куче...)))) так сказать для красоты
PM MAIL   Вверх
emmanuil
Дата 5.2.2009, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: 1
Всего: 3



Цитата(WarHog @  5.2.2009,  11:49 Найти цитируемый пост)
emmanuil, как я понимаю, при генерации машинного кода JIT-компилятор в генерируемой им внутренней таблице корней  указывает диапазон байт, в котором на данный корень есть ссылки. GC, находясь в определенном месте при вызове, смотрит, какие корни действительны в этой точке вызова, а какие - нет, именно по этой таблице, генерируемой JIT-компилятором

Наверное это вопрос, а не критика. smile
(пример из рихтера)
Код

public static class Program {

    public static void Main() {
        // Создание объекта Timer, вызывающего метод TimerCallback 
        // каждые 2000 миллисекунд. 
        System.Threading.Timer t = new System.Threading.Timer(TimerCallback, null, 0, 2000);
        // Ждем, когда пользователь нажмет Enter. 
        Console.ReadLine();
    }

    private static void TimerCallback(Object o) {
        // Отображение даты/времени вызова этого метода. 
        Console.WriteLine("In TimerCallback: " + DateTime.Now);
        // Принудительный вызов сборщика мусора в этой программе. 
        GC.Collect();
    }
}
Обычный режим.
JIT-сгенирил все свою лабуду и корни в том числе.
После вызова GC.Collect(); сборщик удалит объект (речь идет о Timer), так как при поиске ссылок он не найдет ничего.
Режим отладки.
JIT-сгенирил все свою лабуду и корни в том числе, плюс сгенерил еще и внутреннюю таблицу, исскуственные ссылки так сказать, чтобы при вызове GC.Collect(); сборщик увидел что есть ссылки и не удалил объект до конца метода мэин. По простому так.
JIT не занимается поиском смертников, для этого и создан сборщик и он управляет жизнью объекта так сказать.

Это сообщение отредактировал(а) emmanuil - 5.2.2009, 14:19
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0570 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.