LINUX.ORG.RU

Зачем нужны GC, Java, .NET?


0

0

Имеем для каждого объекта счетчик ссылок на него. Исчезает последняя ссылка --> объект удаляется. Запрещаем при этом ручную работу с указателями. Получаем то же самое, что и в Java или .NET, но без огромного оверхеда. Те же Genie или Vala работают по такому принципу, хотя там и есть возможность рулить памятью руками (но чисто опционально). При этом они не таскают за собой большую дуру под названием JVM и работают куда быстрее.

Так в чем прикол «безопасного программирования» по Сану или Микрософту в таком случае?

Ответ на: комментарий от Booster

>с возможностью утечек ресурсов отличных от памяти.
в жабе вместо деструкторов есть try finally

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

>Циклические ссылки? Действительно зачем ссылка на ссылку?

Эм... Двусвязный список и вот тебе циклические ссылки.

Waterlaz ★★★★★
()

Я не очень большой знаток GC, читал только Рихтера по .Net.
На самом деле нет ничего однозначно лучшего. Плюс GC в скорости выделения памяти(большой пул, более хорошая организация хипа). В скорости выделения памяти .Net превосходит С++. Но Рихтер писал, что GC идеален для памяти бесконечного размера, к сожалению часто это не так. Тут некоторые спрашивали чем плох GC. Накладными расходами же. Могу сказать правда только за .Net. Останов всех потоков, обход всех объектов, доплнительная работа с хипом совсем не бесплатны и намного дороже чем в С++. Ну и про подводные камни я уже писал. В .Net ввели всё-же возможность некоторого ручного управления, без него иногда очень плохо.

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

>Эм... Двусвязный список и вот тебе циклические ссылки.
Всё равно не понял. Есть два объекта A и B, в каждом из них есть ссылка на каждый. A хранит ссылку на B, B на A. При удалении A, счетчик на реальный объект A`, уменьшается с 2 до 1, при этом и счётчик на B тоже становится 1. Когда удаляется B, все счётчики становятся 0 и всё благополучно уничтожается.

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

>Эм... Двусвязный список и вот тебе циклические ссылки.
Я имел ввиду ссылку на смартпоитер, а не циклическую связь объектов.

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

>Когда удаляется B, все счётчики становятся 0 и всё благополучно уничтожается.

А ты чуть сложнее ситуацию возьми. Пусть у нас есть взаимно ссылающиеся A и B. И есть внешние ссылки на A и B. Получается, счётчик использования там и там = 2.

A=2, B=2.

Сносим внешнюю ссылку на A:

A=1, B=2.

Сносим внешнюю ссылку на B:

A=1, B=1.

Всё, на объекты никто не ссылается «снаружи», но они не удаляются.

KRoN73 ★★★★★
()

Утечки памяти могут быть и с GC.

Пример:

//Создаём объекты в некоторый контейнер
SuperVector SV(10000);
for (i in 0..9999) 
{
   SV.Add( new MyObject );
}
// Работа с SV
.......
///// Закончили работать и освободим память от ненужных нечётных данных
for (i in 1..9999 step 2) 
{
   SV[i] := 0;
}
Вроде бы всё хорошо и GC подчистит память, но

1) «SV := 0;» мало чем отличается от «Free(SV);»; фактически идёт ручная работа с памятью.

2) SuperVector может хранить у себя ссылку на последний внесенный в него элемент, отдавая его через «SV.LastInserted()». Программист легко может про эту особенность SuperVector забыть или не знать, но ссылка останется и один из 5000 нечётных объектов не удалится, удалится лишь 4999 объектов, а на №9999 останется ссылка у самого SV, а это утечка памяти самая настоящая!

3) При полной очистке SV

for (i in 0..9999) 
{
   SV[i] := 0;
}
Что бы избежать ситуации пункта 2 надо вызвать ещё и «SV.ClearHistory()» после этого цикла, что бы сказать GC, что точно больше ничего из SV не надо и он должен очистить свою историю вставок. Иначе будет утечка памяти на элементе №9999! Не говоря уже о том, что это тоже фактически ручная работа с памятью.

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

1)

SuperVector SV; 
SV.Add( new MyObject ); 
SV[0] := 0; 
Чтобы избежать утечки памяти в данном примере, контейнер SuperVector обязан очистить свою внутреннюю ссылку на последний добавленный объект на строке с SV[0] := 0; и тогда SV.LastInserted() вернёт NULL.

2)

SuperVector SV; 
SV.Add( new MyObject ); 
MyObject Obj := SV[0];
SV[0] := 0; 

В этом примере получиться, что SV, действуя как в первом примере, очитит ссылку для избежания утечки памяти и SV.LastInserted() вернёт NULL, но последний вставленный объект ведь продолжит существовать. Таким образом история вектора будет врать. Это всё равно что если в какое-то режимное помещение входят-выходят люди и в журнал посещений записывают всех входящих и выходящих. Но когда последний вошедший туда человек выходит, его же нельзя удалять из журнала последних вошедших и функция ЖурналПосещений.LastInserted() обязан вернуть имя этого человека! Хоть он и вышел и в помещении больше не присутствует.

В языках без GC нет никакой проблемы, потому что LastInserted вернёт или копию объекта последнего объекта или адрес последнего объекта. Будет ли этот адрес ссылаться на действующий объект остаётся на программисте. Но в языке с GC нерешаемая проблема получается. Или утечка памяти или лживая история вставок в вектор.

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

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

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

>Всё, на объекты никто не ссылается «снаружи», но они не удаляются.
Снова не понял. Когда удалятся A и B, то всё нормально удалиться.

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

Объект А сделал для себя объекты Н1 и Н2, сделал между ними взаимные ссылки (Н1 на Н2) и (Н2 на Н1). Потом отказались от использования А.
Но Н1 и Н2 ссылаются друг на друга со счётчиком ссылок 1 и не могут быть из-за этого удалены, хоть к ним и нет доступа из программы.

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

>Но Н1 и Н2 ссылаются друг на друга со счётчиком ссылок 1 и не могут быть из-за этого удалены, хоть к ним и нет доступа из программы.
Почему не могут-то? Если они указывают друг на друга, то да. А если они указывают на реальные объекты, то вполне могут.

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

>Объект А сделал для себя объекты Н1 и Н2, сделал между ними взаимные ссылки (Н1 на Н2) и (Н2 на Н1)

Почему не могут-то? Если они указывают друг на друга, то да

Прочитай еще раз то, что написал ВОЕНКОМ

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

>Прочитай еще раз то, что написал ВОЕНКОМ
Уже читал. И как удаляются циклические связи уже писал. То что их создаёт внешний объект ничего не меняет.

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

>Снова не понял. Когда удалятся A и B, то всё нормально удалиться.

Ещё раз и по буквам.

Начальная ситуация. Объекты A, B, X, Y.

Ссылаются:

X -> A
Y -> B
B -> A
A -> B

Счётчик ссылок на A равен двум (ссылаются X и B).
Счётчик ссылок на B равен двум (ссылаются Y и A).

Удаляем ссылку X -> A. Итог:
На A ссылается только B. Счётчик ссылок равен 1.
B не изменился, на него по-прежнему ссылаются Y и A, счётчик ссылок = 2.

Удаляем ссылку Y -> B. Итог:
На A ссылается только B. Счётчик равен 1.
На B ссылается только A. Счётчик равен 1.

Всё, на связку объектов A и B больше никто не ссылается. Но они ссылаются друг на друга. Счётчик ссылок больше не будет уменьшаться (программа больше ничего не знает про эти объекты). Но объекты не освобождают память.

Если и в таком виде непонятно - то о разработке сборки мусора тебе явно рано ещё думать :)

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

>Всё, на связку объектов A и B больше никто не ссылается. Но они ссылаются друг на друга. Счётчик ссылок больше не будет уменьшаться (программа больше ничего не знает про эти объекты). Но объекты не освобождают память.
Как это счётчик больше не будет меняться? Объекты A и B удалять не надо? Странная логика.

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

Конечно не надо их удалять сборщику мусора. Потому что у них счётчик ссылок застрянет на 1 и GC будет на это основании думать, что А и Б где-то используются в программе.

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

>Конечно не надо их удалять сборщику мусора. Потому что у них счётчик ссылок застрянет на 1 и GC будет на это основании думать, что А и Б где-то используются в программе.
Как это застрянет? Мы же говорим о ссылках. При удалении ссылки A, уменьшаться счётчики на реальные объекты A' и B'. При удалении ссылки B, всё счастливо удалиться. То что кто-то ещё владел объектами, удалился и уменьшил кол-во ссылок ничего не меняет.

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

Это же не деструкторы, которые раскручивают стек, удаляя связанные объекты. Счётчики ссылок стеки не раскручивают и по сцылкам не ходят.
Они просто тупо и локально уменьшают счётчик у отязываемого объекта.

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

tripplefacepalm...

объектA:
   какие-то данные
   ссылка на B

объектB:
   какие-то данные
   ссылка на A

объектX:
   какие-то данные
   ссыдка на A

функция main:
   ссылка на X

Из функции main удаляем объект X. Объекты A и B остаются и ссылаются друг на друга.

ЗЫ по моему ты тролль.

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

>Это же не деструкторы, которые раскручивают стек, удаляя связанные объекты. Счётчики ссылок стеки не раскручивают и по сцылкам не ходят.
Они просто тупо и локально уменьшают счётчик у отязываемого объекта.
При чём здесь деструкторы? Ссылка удалилась(вышла из своей области видимости), счётчик уменьшился, счётчик дошел до нуля - удаляем объект.

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

>>Счетчики не дойдут до нуля.

Дойдут.


Я выше привёл пример. Распиши, в какой момент там счётчики окажутся с нулевыми значениями :)

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

Как они дойдут?

У тебя остается два объекта. Каждый ссылается на другой(А на Б, Б на А).

Из остальной программы никто не ссылается ни на А ни на Б. Все!

ТЫ все еще думаешь, что дойдет?

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

>ЗЫ по моему ты тролль.

Я тоже начинаю к этому склоняться. Не может быть у человека на ЛОРе СМ настолько Г :)

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

>Как они дойдут?
У тебя остается два объекта. Каждый ссылается на другой(А на Б, Б на А).
Из остальной программы никто не ссылается ни на А ни на Б. Все!
ТЫ все еще думаешь, что дойдет?

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

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

GC на счётчиках сцылок не работает с областью видимости. Выход из области видимости переменной, сцылающейся на объект, лишь уменьшит счётчик у объекта.

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

>Выход из области видимости переменной, сцылающейся на объект, лишь уменьшит счётчик у объекта.
Да, но уменьшает ведь и если 0, то в утиль.

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

Опять таки GC и смарты несколько разные вещи. В языках с GC, cмарты лиш помогают GC.

Booster ★★
()

Признаю, не прав, взаимная блокировка получается. Извиняюсь за троллизм.

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

> Плюс GC в скорости выделения памяти(большой пул, более хорошая организация хипа). В скорости выделения памяти .Net превосходит С++.

Приехали. Ты сравниваешь язык и его рантайм. Не стыдно?

Реализация хипа - это усмотрение разработчиков компилятора и его либ. Как напишешь, так и будет работать.

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

via http://www.infoplease.com/computers/jargon/koans.html#id3095102

Moon instructs a student

One day a student came to Moon and said: “I understand how to make a better garbage collector. We must keep a reference count of the pointers to each cons.”

Moon patiently told the student the following story:

“One day a student came to Moon and said: ‘I understand how to make a better garbage collector...

[Ed. note: Pure reference-count garbage collectors have problems with circular structures that point to themselves.]

anonymous
()

Юзайте статические переменные, и не будет необходимости в освобождении памяти!

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

В моей практике это обычно делается вокруг c++ программ. Смотри asterisk, любые субд с протекторами, вендовые сервисы с автоперезапуском.

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