LINUX.ORG.RU
ФорумTalks

Идея автосбора мусора С#


0

0

Сейчас изучаю С#. До этого программировал на Си и немного на С++ (больше как-то на Си). Вот дошел до автосбора мусора.

Не знаю, люди, но у меня как-то двоякое впечатление пока. С одной стороны приятна такая забота о программисте (даже трогательна!), но с другой... Мне кажется это неудобным. Может это после Си. Но я так не знаю, когда объект будет разрушен, не знаю сколько точно памяти нужно... и т.д. Привычка все делать вручную. Или желание тотального контроля? :)

Знаю, знаю, что, типа, добавь компу своему еще пару гигов памяти... :)

★★★★★

> Привычка все делать вручную. Или желание тотального контроля?

идиотство это.

anonymous
()

Если боитесь потери контроля над программой - изучите механизмы современных сборщиков мусора.

Legioner ★★★★★
()

>Или желание тотального контроля?

меня интересует именно это.

generatorglukoff ★★
()
Ответ на: комментарий от Legioner

> Если боитесь потери контроля над программой - изучите механизмы современных сборщиков мусора.

И чем это поможет? А чем это поможет, когда реализация сборщика изменится?

tailgunner ★★★★★
()

>Но я так не знаю, когда объект будет разрушен, не знаю сколько точно памяти нужно... и т.д. Привычка все делать вручную. Или желание тотального контроля? :)

А драйверы для звуковой карты ты тоже сам себе пишешь? Или линуксовским пользуешься? А не боишься, что в готовом могут быть утечки памяти? Не лучше ли вручную самому прописать, как звуковухе работать?

капча veseman намекает

anonymous
()

сборка мусора - это не "забота о программисте", а средство расширить язык абстракциями, недоступными при ручном управлении памятью. большая часть "замечательных возможностей" тех же LISP, Tcl, Haskell без сборки мусора просто невозможна

хотя в случае с C# всё это только отчасти верно :)

jtootf ★★★★★
()
Ответ на: комментарий от mutronix

>А какая тебе разница, когда он будет разрушен? Нет указателей - нет проблем с памятью

"разрушен" и "будет освобождена память" это как бы две большие разницы. RAII/RRID намекают

jtootf ★★★★★
()
Ответ на: комментарий от mutronix

>> А какая тебе разница, когда он будет разрушен? Нет указателей - нет проблем с памятью

Проблемы начинают возникать, когда объект - это не просто кусок памяти с какими-то данными, а например ещё и сокет какой-нибудь. В таких случаях "когда он будет разрушен" имеет большое значение, иначе может получиться неслабая утечка ресурсов. Хотя это всё решаемо.

Deleted
()

К сожалению это удобство очень сильно входит в привычку, и если планируешь работать с C# и дальше, то после него аккуратней с C/C++ - начнутся тупые ошибки с (не)удалением. А так вообще GC - штука приятная, я правда тоже долго привыкал, не мог смириться с потерей контроля над "мозгами". А потом как-то привык.

ЗЫ. ИМХО, если учишь C# для себя, то лучше возьми сразу D. Там и GC отключить можно.

ЗЗЫ. Признавайтесь, кто юзал Boehm GC для C/C++? (http://www.hpl.hp.com/personal/Hans_Boehm/gc/). Как оно себя показывает на практике?

k0l0b0k ★★
()
Ответ на: комментарий от k0l0b0k

> Признавайтесь, кто юзал Boehm GC для C/C++? (http://www.hpl.hp.com/personal/Hans_Boehm/gc/). Как оно себя показывает на практике?

Я видел, как его пытались тиспользовать в OpenCM %) Проект помер отчасти из-за глюков во взаимодействии GC, SSL и еще чего-то.

tailgunner ★★★★★
()
Ответ на: комментарий от Deleted

>Проблемы начинают возникать, когда объект - это не просто кусок памяти с какими-то данными, а например ещё и сокет какой-нибудь. В таких случаях "когда он будет разрушен" имеет большое значение, иначе может получиться неслабая утечка ресурсов. Хотя это всё решаемо.

В подобных случаях в C# у объектов есть метод Dispose, всю работу заключаешь в using, типа:

using (HttpWebResponse response = request.GetResponse()) { Console.WriteLine(response.StatusDescription); }

true
()
Ответ на: комментарий от Deleted

>Проблемы начинают возникать, когда объект - это не просто кусок памяти с какими-то данными, а например ещё и сокет какой-нибудь.

Сокеты как и прочие файловые дескрипторы везде приходится открывать/закрывать вручную или С# уже научился делать это автоматически? Я просто не знаком с шарпом

mutronix ★★★★
()
Ответ на: комментарий от jtootf

>"разрушен" и "будет освобождена память" это как бы две большие разницы. RAII/RRID намекают

Не понял, что ты хотел этим сказать?

mutronix ★★★★
()
Ответ на: комментарий от k0l0b0k

>ЗЫ. ИМХО, если учишь C# для себя, то лучше возьми сразу D. Там и GC отключить можно.

Так в шарпе вроде тоже был режим ручного управления памятью

mutronix ★★★★
()
Ответ на: комментарий от mutronix

>>"разрушен" и "будет освобождена память" это как бы две большие разницы. RAII/RRID намекают

>Не понял, что ты хотел этим сказать?

то самое, что и сказал. "выделить память под объект" это одно, "создать объект в этой памяти" - другое; аналогично касательно разрушения. принцип RAII работает независимо от механизма выделения/освобождения памяти - однако его использование в том же C# весьма отличается от принятого в C/C++ (даже с учётом семантического кариеса а-ля "умные указатели")

вместо адовых delete будут адовые finally. ручная работа как была так и осталась (:

jtootf ★★★★★
()
Ответ на: комментарий от mutronix

>Сокеты как и прочие файловые дескрипторы везде приходится открывать/закрывать вручную или С# уже научился делать это автоматически? Я просто не знаком с шарпом

RAII, чёрт возьми. если есть автоматическое управление разрушением объекта - есть и автоматическое освобождение ресурсов, захваченных этим объектом. независимо от языка

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

Дык, в случае с файловыми дескрипторами их закрытие осуществятся явным вызовом close(), иначе при выходе из программы, не?

mutronix ★★★★
()
Ответ на: комментарий от mutronix

>Так в шарпе вроде тоже был режим ручного управления памятью

не совсем. можно просто "помочь" GC в сборке мусора, или зафиксировать объект в памяти (keyword fixed, чтобы ГЦ его не грохнул при вызове unmanaged-операций, очень помогает при работе с OpenGL). А отключить GC полностью нельзя (по типу как позволяют это сделать Python и Ruby - gc.disable(), емнип).

k0l0b0k ★★
()
Ответ на: комментарий от mutronix

>Дык, в случае с файловыми дескрипторами их закрытие осуществятся явным вызовом close(), иначе при выходе из программы, не?

вызов этот может находится в деструкторе - а время жизни объекта может контролироваться компилятором: если он был создан на стеке, или хранится внутре scoped_ptr какого-нибудь, или мало ли ещё чего

jtootf ★★★★★
()
Ответ на: комментарий от mutronix

>Дык, в случае с файловыми дескрипторами их закрытие осуществятся явным вызовом close(), иначе при выходе из программы, не?

ну нормально спроектированный класс вызовет close() в своем деструкторе (или в финалайзере или dispose() или еще что-то наподобие). Вопрос только _когда_ это произойдет... Т.е. если вас не устраивает что GC будет решать за вас когда закрыть файл, то делайте ручками.

k0l0b0k ★★
()
Ответ на: комментарий от k0l0b0k

> ну нормально спроектированный класс вызовет close() в своем деструкторе (или в финалайзере или dispose() или еще что-то наподобие). Вопрос только _когда_ это произойдет... Т.е. если вас не устраивает что GC будет решать за вас когда закрыть файл, то делайте ручками.

А что будет когда в деструкторе подобный close вывалит какой-нибудь очень специфический эксепшен?

anonymous
()

>Может это после Си. Но я так не знаю, когда объект будет разрушен, не знаю сколько точно памяти нужно... и т.д.

Может это после Ассемблера. Но я так не знаю, какие инструкции применит компилятор, сколько памяти потребуется под код... и т.д.

;)

KRoN73 ★★★★★
()
Ответ на: комментарий от anonymous

> А что будет когда в деструкторе подобный close вывалит какой-нибудь очень специфический эксепшен?

Нехрен при закрытии исключениями кидаться. Шла бы речь про C++, написал бы просто "нефиг исключения кидать".

anonymous
()
Ответ на: комментарий от Legioner

> А что будет когда в finally подобный close вывалит какой-нибудь очень специфический эксепшен?

В текущем методе произойдет ошибка времени выполнения, которая вполне может быть изолирована на более высоком уровне абстракции и не приводить к отказу всей системы.

anonymous
()
Ответ на: комментарий от anonymous

Если finally выполнялся при нормальном состоянии то да, всё в шоколаде. А если finally выполнялся в ходе раскрутки стека из за другого исключения, исходное исключение тупо потеряется. И всё. В надёжных системах это недопустимо. Поэтому из finally точно так же не должны вылетать никакие исключения.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Исходное - то, из за которого шла раскрутка стека.

Legioner ★★★★★
()

>Привычка все делать вручную. Или желание тотального контроля? :)

Пережиток прошлого, ты подсел на СИ дружок

anonymous
()
Ответ на: комментарий от KRoN73

Кстати. Открыл вчера для себя mono -v -v -v mysource.cs -> выведет в stdout ассемблерный код программы которая дана ему на C# (mysource.cs) + много всякой инфы о процессе выполнения (чем больше -v тем больше инфы)

k0l0b0k ★★
()
Ответ на: комментарий от Legioner

>исходное исключение тупо потеряется.

да, кстати, .NET потеряет исключение "1":
try
{
    try
    {
         throw new Exception("1");
    }
    finally
    {
         throw new Exception("2");
    }
}
catch (Exception ex)
{
}

А мог бы в InnerException записать...

k0l0b0k ★★
()

На работе люди из другого проекта рассказали. Не помню точно всех подробностей, но примерно суть такова. Есть код от другой команды, Java. Он использует JDBC и закрытие коннекций американцы воткнули в финализаторы. Получилось так, что когда мало памяти, всё работает, а когда много - нет. Сейчас как workaround сделана принудительная сборка мусора каждые 3 чтоли минуты, а вообще, тяжёло будет это разгребать.

Score-49
()
Ответ на: комментарий от Legioner

> Если finally выполнялся при нормальном состоянии то да, всё в шоколаде. А если finally выполнялся в ходе раскрутки стека из за другого исключения, исходное исключение тупо потеряется. И всё. В надёжных системах это недопустимо. Поэтому из finally точно так же не должны вылетать никакие исключения.

> Исходное - то, из за которого шла раскрутка стека.

Они не 'не вылетают', они хоронятся в finally-блоке самим программистом в виде catch (everyting){;}, ну в лучшем случае в лог сообщение идет, но такой эксепшен для работающей системы будет полностью заигнорирован. С моей точки зрения, это проблема синтаксиса и семантики языка, а подобное решение просто 'меньшее зло' с точки зрения разработчика: либо ставим в приоритет эксепшн try-блока и хороним эксепшн finally-блока, либо наоборот.

Проблема в том, что finally является безусловным переходом и понятия не имеет о состоянии try-блока. Если рассматривать при автоматической работе с ресурсами весь блок как транзакцию, то ,по аналогии с БД, он должнен в итоге сделать один условный переход: либо закоммититься, либо откатиться. Тем самым, если finally заменить на commit и rollback, то первый должен отрабатывать после успешного завершения блока, а второй после неудачного. Соответственно при неудачном завершении commit и rollback получим CommitException и RollbackException. Rollback же вполне может связать свой эксепшен с проблемой возникшей в работе блока.

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

Привязывать же потенциально опасный пользовательский код к системным потокам, вроде gc, по-моему весьма ущербно.

anonymous
()
Ответ на: комментарий от Score-49

>Он использует JDBC и закрытие коннекций американцы воткнули в финализаторы. Получилось так, что когда мало памяти, всё работает, а когда много - нет. Сейчас как workaround сделана принудительная сборка мусора каждые 3 чтоли минуты, а вообще, тяжёло будет это разгребать.

Хм, какието они индусы эти ваши американцы, когда мы так делали то оставляли метод close() на произвол юзера, и в финализе проверяли если юзер прошляпил и не закрыл то закрываем.

wfrr ★★☆
()

> Но я так не знаю, когда объект будет разрушен, не знаю сколько точно памяти нужно... и т.д. Привычка все делать вручную. Или желание тотального контроля? :)

Не не не, не надо вручную, наелись уже. Попрограммировал в своё время COM-объекты на C API (и ассемблере), без ++ -- это куча спрятанных граблей. Тут под BSTR выделяет память клиент, тут сервер. Тут он сразу помещается, а тут нужен ещё один вызов, запросить сколько памяти надо. На ++ оно посахарнее синтаксически, со смартпоинтерами, но тоже не фонтан. Нужно нормальное API сразу, без скрытых детских грабелек.

Что можно сделать с GC и чего нельзя без него -- так это first-class objects. Создать объект, поюзать, убрать ссылку на него, и знать, что при выходе из scope он гарантированно прибъётся.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.